crypto_sync: synchronous routines for inter-peer crypto.

This is used by the opening daemon, for example.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2017-02-21 15:15:29 +10:30
parent f66445c1d1
commit e3f2d72d4d
5 changed files with 119 additions and 28 deletions

View File

@ -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 \

34
lightningd/crypto_sync.c Normal file
View File

@ -0,0 +1,34 @@
#include <ccan/read_write_all/read_write_all.h>
#include <lightningd/crypto_sync.h>
#include <lightningd/cryptomsg.h>
#include <wire/wire_sync.h>
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;
}

12
lightningd/crypto_sync.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef LIGHTNING_LIGHTNINGD_CRYPTO_SYNC_H
#define LIGHTNING_LIGHTNINGD_CRYPTO_SYNC_H
#include "config.h"
#include <ccan/short_types/short_types.h>
#include <ccan/tal/tal.h>
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 */

View File

@ -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,
u8 *cryptomsg_encrypt_msg(const tal_t *ctx,
struct crypto_state *cs,
const u8 *msg,
struct io_plan *(*next)(struct io_conn *,
struct peer *))
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.
*/

View File

@ -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 */