diff --git a/lightningd/Makefile b/lightningd/Makefile index 986819c06..3ba8c5f8d 100644 --- a/lightningd/Makefile +++ b/lightningd/Makefile @@ -37,6 +37,7 @@ LIGHTNINGD_LIB_SRC := \ lightningd/channel_config.c \ lightningd/commit_tx.c \ lightningd/cryptomsg.c \ + lightningd/crypto_sync.c \ lightningd/funding_tx.c \ lightningd/htlc_tx.c \ lightningd/key_derive.c \ diff --git a/lightningd/crypto_sync.c b/lightningd/crypto_sync.c new file mode 100644 index 000000000..86054cf71 --- /dev/null +++ b/lightningd/crypto_sync.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include + +bool sync_crypto_write(struct crypto_state *cs, int fd, const void *msg) +{ + u8 *enc = cryptomsg_encrypt_msg(msg, cs, msg); + bool ret; + + ret = wire_sync_write(fd, enc); + tal_free(enc); + return ret; +} + +u8 *sync_crypto_read(const tal_t *ctx, struct crypto_state *cs, int fd) +{ + u8 hdr[18], *enc, *dec; + u16 len; + + if (!read_all(fd, hdr, sizeof(hdr))) + return NULL; + + if (!cryptomsg_decrypt_header(cs, hdr, &len)) + return NULL; + + enc = tal_arr(ctx, u8, len); + if (!read_all(fd, enc, len)) + return tal_free(enc); + + dec = cryptomsg_decrypt_body(ctx, cs, enc); + tal_free(enc); + return dec; +} diff --git a/lightningd/crypto_sync.h b/lightningd/crypto_sync.h new file mode 100644 index 000000000..df190590e --- /dev/null +++ b/lightningd/crypto_sync.h @@ -0,0 +1,12 @@ +#ifndef LIGHTNING_LIGHTNINGD_CRYPTO_SYNC_H +#define LIGHTNING_LIGHTNINGD_CRYPTO_SYNC_H +#include "config.h" +#include +#include + +struct crypto_state; + +bool sync_crypto_write(struct crypto_state *cs, int fd, const void *msg); +u8 *sync_crypto_read(const tal_t *ctx, struct crypto_state *cs, int fd); + +#endif /* LIGHTNING_LIGHTNINGD_CRYPTO_SYNC_H */ diff --git a/lightningd/cryptomsg.c b/lightningd/cryptomsg.c index a62d8d44b..a1fa1a807 100644 --- a/lightningd/cryptomsg.c +++ b/lightningd/cryptomsg.c @@ -85,13 +85,17 @@ static void le64_nonce(unsigned char *npub, u64 nonce) memcpy(npub + zerolen, &le_nonce, sizeof(le_nonce)); } -static struct io_plan *peer_decrypt_body(struct io_conn *conn, - struct crypto_state *cs) +u8 *cryptomsg_decrypt_body(const tal_t *ctx, + struct crypto_state *cs, const u8 *in) { unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES]; unsigned long long mlen; - u8 *decrypted = tal_arr(cs->in, u8, tal_count(cs->in) - 16), *in; - struct io_plan *plan; + size_t inlen = tal_count(in); + u8 *decrypted; + + if (inlen < 16) + return NULL; + decrypted = tal_arr(ctx, u8, inlen - 16); le64_nonce(npub, cs->rn++); @@ -104,17 +108,28 @@ static struct io_plan *peer_decrypt_body(struct io_conn *conn, */ if (crypto_aead_chacha20poly1305_ietf_decrypt(decrypted, &mlen, NULL, - memcheck(cs->in, - tal_count(cs->in)), - tal_count(cs->in), + memcheck(in, inlen), + inlen, NULL, 0, npub, cs->rk.u.u8) != 0) { /* FIXME: Report error! */ - return io_close(conn); + return tal_free(decrypted); } assert(mlen == tal_count(decrypted)); maybe_rotate_key(&cs->rn, &cs->rk, &cs->r_ck); + return decrypted; +} + +static struct io_plan *peer_decrypt_body(struct io_conn *conn, + struct crypto_state *cs) +{ + struct io_plan *plan; + u8 *in, *decrypted; + + decrypted = cryptomsg_decrypt_body(cs->in, cs, cs->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 @@ -127,8 +142,7 @@ static struct io_plan *peer_decrypt_body(struct io_conn *conn, return plan; } -static struct io_plan *peer_decrypt_header(struct io_conn *conn, - struct crypto_state *cs) +bool cryptomsg_decrypt_header(struct crypto_state *cs, u8 *hdr, u16 *lenp) { unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES]; unsigned long long mlen; @@ -148,15 +162,27 @@ static struct io_plan *peer_decrypt_header(struct io_conn *conn, */ if (crypto_aead_chacha20poly1305_ietf_decrypt((unsigned char *)&len, &mlen, NULL, - memcheck(cs->in, - tal_count(cs->in)), - tal_count(cs->in), + memcheck(hdr, + tal_count(hdr)), + tal_count(hdr), NULL, 0, npub, cs->rk.u.u8) != 0) { /* FIXME: Report error! */ - return io_close(conn); + return false; } assert(mlen == sizeof(len)); + *lenp = be16_to_cpu(len); + return true; +} + +static struct io_plan *peer_decrypt_header(struct io_conn *conn, + struct crypto_state *cs) +{ + u16 len; + + if (!cryptomsg_decrypt_header(cs, cs->in, &len)) + return io_close(conn); + tal_free(cs->in); /* BOLT #8: @@ -164,7 +190,7 @@ static struct io_plan *peer_decrypt_header(struct io_conn *conn, * * Read _exactly_ `l+16` bytes from the network buffer, let * the bytes be known as `c`. */ - cs->in = tal_arr(cs, u8, (u32)be16_to_cpu(len) + 16); + cs->in = tal_arr(cs, u8, (u32)len + 16); return io_read(conn, cs->in, tal_count(cs->in), peer_decrypt_body, cs); } @@ -196,21 +222,17 @@ static struct io_plan *peer_write_done(struct io_conn *conn, return cs->next_out(conn, cs->peer); } -struct io_plan *peer_write_message(struct io_conn *conn, - struct crypto_state *cs, - const u8 *msg, - struct io_plan *(*next)(struct io_conn *, - struct peer *)) +u8 *cryptomsg_encrypt_msg(const tal_t *ctx, + struct crypto_state *cs, + const u8 *msg) { unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES]; unsigned long long clen, mlen = tal_count(msg); be16 l; int ret; + u8 *out; - assert(!cs->out); - - cs->out = tal_arr(cs, u8, sizeof(l) + 16 + mlen + 16); - cs->next_out = next; + out = tal_arr(cs, u8, sizeof(l) + 16 + mlen + 16); /* BOLT #8: * @@ -236,7 +258,7 @@ struct io_plan *peer_write_message(struct io_conn *conn, * * A zero-length byte slice is to be passed as the AD */ le64_nonce(npub, cs->sn++); - ret = crypto_aead_chacha20poly1305_ietf_encrypt(cs->out, &clen, + ret = crypto_aead_chacha20poly1305_ietf_encrypt(out, &clen, (unsigned char *) memcheck(&l, sizeof(l)), sizeof(l), @@ -250,7 +272,7 @@ struct io_plan *peer_write_message(struct io_conn *conn, tal_hexstr(trc, &l, sizeof(l)), tal_hexstr(trc, npub, sizeof(npub)), tal_hexstr(trc, &cs->sk, sizeof(cs->sk)), - tal_hexstr(trc, cs->out, clen)); + tal_hexstr(trc, out, clen)); #endif /* BOLT #8: @@ -262,7 +284,7 @@ struct io_plan *peer_write_message(struct io_conn *conn, * * The nonce `sn` MUST be incremented after this step. */ le64_nonce(npub, cs->sn++); - ret = crypto_aead_chacha20poly1305_ietf_encrypt(cs->out + clen, &clen, + ret = crypto_aead_chacha20poly1305_ietf_encrypt(out + clen, &clen, memcheck(msg, mlen), mlen, NULL, 0, @@ -275,11 +297,25 @@ struct io_plan *peer_write_message(struct io_conn *conn, tal_hexstr(trc, msg, mlen), tal_hexstr(trc, npub, sizeof(npub)), tal_hexstr(trc, &cs->sk, sizeof(cs->sk)), - tal_hexstr(trc, cs->out + 18, clen)); + tal_hexstr(trc, out + 18, clen)); #endif maybe_rotate_key(&cs->sn, &cs->sk, &cs->s_ck); + return out; +} + +struct io_plan *peer_write_message(struct io_conn *conn, + struct crypto_state *cs, + const u8 *msg, + struct io_plan *(*next)(struct io_conn *, + struct peer *)) +{ + assert(!cs->out); + + cs->out = cryptomsg_encrypt_msg(cs, cs, msg); + cs->next_out = next; + /* BOLT #8: * * Send `lc || c` over the network buffer. */ diff --git a/lightningd/cryptomsg.h b/lightningd/cryptomsg.h index 675bbdfec..2cfef25ff 100644 --- a/lightningd/cryptomsg.h +++ b/lightningd/cryptomsg.h @@ -49,4 +49,12 @@ struct io_plan *peer_write_message(struct io_conn *conn, void towire_crypto_state(u8 **pptr, const struct crypto_state *cs); void fromwire_crypto_state(const u8 **ptr, size_t *max, struct crypto_state *cs); + +/* Low-level functions for sync comms. */ +u8 *cryptomsg_encrypt_msg(const tal_t *ctx, + struct crypto_state *cs, + const u8 *msg); +bool cryptomsg_decrypt_header(struct crypto_state *cs, u8 *hdr, u16 *lenp); +u8 *cryptomsg_decrypt_body(const tal_t *ctx, + struct crypto_state *cs, const u8 *in); #endif /* LIGHTNING_LIGHTNINGD_CRYPTOMSG_H */