mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
lightningd/cryptomsg: split raw crypto_state vs peer_crypto_state
Raw crypto_state is what we send across the wire: the peer one is for use in async crypto io routines (peer_read_message/peer_write_message). Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
6cf8a19881
commit
90737371d0
@ -122,22 +122,22 @@ u8 *cryptomsg_decrypt_body(const tal_t *ctx,
|
||||
}
|
||||
|
||||
static struct io_plan *peer_decrypt_body(struct io_conn *conn,
|
||||
struct crypto_state *cs)
|
||||
struct peer_crypto_state *pcs)
|
||||
{
|
||||
struct io_plan *plan;
|
||||
u8 *in, *decrypted;
|
||||
|
||||
decrypted = cryptomsg_decrypt_body(cs->in, cs, cs->in);
|
||||
decrypted = cryptomsg_decrypt_body(pcs->in, &pcs->cs, pcs->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
|
||||
* next_in (could free itself) */
|
||||
in = tal_steal(NULL, cs->in);
|
||||
cs->in = NULL;
|
||||
in = tal_steal(NULL, pcs->in);
|
||||
pcs->in = NULL;
|
||||
|
||||
plan = cs->next_in(conn, cs->peer, decrypted);
|
||||
plan = pcs->next_in(conn, pcs->peer, decrypted);
|
||||
tal_free(in);
|
||||
return plan;
|
||||
}
|
||||
@ -174,31 +174,32 @@ bool cryptomsg_decrypt_header(struct crypto_state *cs, u8 hdr[18], u16 *lenp)
|
||||
}
|
||||
|
||||
static struct io_plan *peer_decrypt_header(struct io_conn *conn,
|
||||
struct crypto_state *cs)
|
||||
struct peer_crypto_state *pcs)
|
||||
{
|
||||
u16 len;
|
||||
|
||||
if (!cryptomsg_decrypt_header(cs, cs->in, &len))
|
||||
if (!cryptomsg_decrypt_header(&pcs->cs, pcs->in, &len))
|
||||
return io_close(conn);
|
||||
|
||||
tal_free(cs->in);
|
||||
tal_free(pcs->in);
|
||||
|
||||
/* BOLT #8:
|
||||
*
|
||||
* * Read _exactly_ `l+16` bytes from the network buffer, let
|
||||
* the bytes be known as `c`.
|
||||
*/
|
||||
cs->in = tal_arr(cs, u8, (u32)len + 16);
|
||||
return io_read(conn, cs->in, tal_count(cs->in), peer_decrypt_body, cs);
|
||||
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 crypto_state *cs,
|
||||
struct peer_crypto_state *pcs,
|
||||
struct io_plan *(*next)(struct io_conn *,
|
||||
struct peer *,
|
||||
u8 *msg))
|
||||
{
|
||||
assert(!cs->in);
|
||||
assert(!pcs->in);
|
||||
/* BOLT #8:
|
||||
*
|
||||
* ### Decrypting Messages
|
||||
@ -208,16 +209,16 @@ struct io_plan *peer_read_message(struct io_conn *conn,
|
||||
*
|
||||
* * Read _exactly_ `18-bytes` from the network buffer.
|
||||
*/
|
||||
cs->in = tal_arr(cs, u8, 18);
|
||||
cs->next_in = next;
|
||||
return io_read(conn, cs->in, 18, peer_decrypt_header, cs);
|
||||
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 crypto_state *cs)
|
||||
struct peer_crypto_state *pcs)
|
||||
{
|
||||
cs->out = tal_free(cs->out);
|
||||
return cs->next_out(conn, cs->peer);
|
||||
pcs->out = tal_free(pcs->out);
|
||||
return pcs->next_out(conn, pcs->peer);
|
||||
}
|
||||
|
||||
u8 *cryptomsg_encrypt_msg(const tal_t *ctx,
|
||||
@ -230,7 +231,7 @@ u8 *cryptomsg_encrypt_msg(const tal_t *ctx,
|
||||
int ret;
|
||||
u8 *out;
|
||||
|
||||
out = tal_arr(cs, u8, sizeof(l) + 16 + mlen + 16);
|
||||
out = tal_arr(ctx, u8, sizeof(l) + 16 + mlen + 16);
|
||||
|
||||
/* BOLT #8:
|
||||
*
|
||||
@ -304,41 +305,27 @@ u8 *cryptomsg_encrypt_msg(const tal_t *ctx,
|
||||
}
|
||||
|
||||
struct io_plan *peer_write_message(struct io_conn *conn,
|
||||
struct crypto_state *cs,
|
||||
struct peer_crypto_state *pcs,
|
||||
const u8 *msg,
|
||||
struct io_plan *(*next)(struct io_conn *,
|
||||
struct peer *))
|
||||
{
|
||||
assert(!cs->out);
|
||||
assert(!pcs->out);
|
||||
|
||||
cs->out = cryptomsg_encrypt_msg(cs, cs, msg);
|
||||
cs->next_out = next;
|
||||
pcs->out = cryptomsg_encrypt_msg(conn, &pcs->cs, msg);
|
||||
pcs->next_out = next;
|
||||
|
||||
/* BOLT #8:
|
||||
* * Send `lc || c` over the network buffer.
|
||||
*/
|
||||
return io_write(conn, cs->out, tal_count(cs->out), peer_write_done, cs);
|
||||
return io_write(conn, pcs->out, tal_count(pcs->out),
|
||||
peer_write_done, pcs);
|
||||
}
|
||||
|
||||
struct crypto_state *crypto_state(struct peer *peer,
|
||||
const struct sha256 *sk,
|
||||
const struct sha256 *rk,
|
||||
const struct sha256 *rck,
|
||||
const struct sha256 *sck,
|
||||
u64 rn, u64 sn)
|
||||
void init_peer_crypto_state(struct peer *peer, struct peer_crypto_state *pcs)
|
||||
{
|
||||
struct crypto_state *cs = tal(peer, struct crypto_state);
|
||||
|
||||
cs->rn = rn;
|
||||
cs->sn = sn;
|
||||
cs->sk = *sk;
|
||||
cs->rk = *rk;
|
||||
cs->s_ck = *sck;
|
||||
cs->r_ck = *rck;
|
||||
cs->peer = peer;
|
||||
cs->out = cs->in = NULL;
|
||||
|
||||
return cs;
|
||||
pcs->peer = peer;
|
||||
pcs->out = pcs->in = NULL;
|
||||
}
|
||||
|
||||
void towire_crypto_state(u8 **ptr, const struct crypto_state *cs)
|
||||
|
@ -15,6 +15,10 @@ struct crypto_state {
|
||||
struct sha256 sk, rk;
|
||||
/* Chaining key for re-keying */
|
||||
struct sha256 s_ck, r_ck;
|
||||
};
|
||||
|
||||
struct peer_crypto_state {
|
||||
struct crypto_state cs;
|
||||
|
||||
/* Peer who owns us: peer->crypto_state == this */
|
||||
struct peer *peer;
|
||||
@ -25,24 +29,19 @@ struct crypto_state {
|
||||
struct io_plan *(*next_out)(struct io_conn *, struct peer *);
|
||||
};
|
||||
|
||||
/* Initializes peer->crypto_state */
|
||||
struct crypto_state *crypto_state(struct peer *peer,
|
||||
const struct sha256 *sk,
|
||||
const struct sha256 *rk,
|
||||
const struct sha256 *rck,
|
||||
const struct sha256 *sck,
|
||||
u64 rn, u64 sn);
|
||||
/* 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 */
|
||||
struct io_plan *peer_read_message(struct io_conn *conn,
|
||||
struct crypto_state *cs,
|
||||
struct peer_crypto_state *cs,
|
||||
struct io_plan *(*next)(struct io_conn *,
|
||||
struct peer *,
|
||||
u8 *msg));
|
||||
|
||||
/* Sends and frees message */
|
||||
struct io_plan *peer_write_message(struct io_conn *conn,
|
||||
struct crypto_state *cs,
|
||||
struct peer_crypto_state *cs,
|
||||
const u8 *msg,
|
||||
struct io_plan *(*next)(struct io_conn *,
|
||||
struct peer *));
|
||||
|
@ -46,7 +46,7 @@ struct peer {
|
||||
struct list_node list;
|
||||
|
||||
u64 unique_id;
|
||||
struct crypto_state *cs;
|
||||
struct peer_crypto_state pcs;
|
||||
|
||||
/* File descriptor corresponding to conn. */
|
||||
int fd;
|
||||
@ -76,10 +76,11 @@ static void destroy_peer(struct peer *peer)
|
||||
static struct peer *setup_new_peer(struct daemon *daemon, const u8 *msg)
|
||||
{
|
||||
struct peer *peer = tal(daemon, struct peer);
|
||||
peer->cs = tal(peer, struct crypto_state);
|
||||
if (!fromwire_gossipctl_new_peer(msg, NULL, &peer->unique_id, peer->cs))
|
||||
|
||||
init_peer_crypto_state(peer, &peer->pcs);
|
||||
if (!fromwire_gossipctl_new_peer(msg, NULL, &peer->unique_id,
|
||||
&peer->pcs.cs))
|
||||
return tal_free(peer);
|
||||
peer->cs->peer = peer;
|
||||
peer->daemon = daemon;
|
||||
peer->error = NULL;
|
||||
peer->msg_out = tal_arr(peer, u8*, 0);
|
||||
@ -102,15 +103,15 @@ static struct io_plan *peer_msgin(struct io_conn *conn,
|
||||
|
||||
case WIRE_CHANNEL_ANNOUNCEMENT:
|
||||
handle_channel_announcement(peer->daemon->rstate, msg, tal_count(msg));
|
||||
return peer_read_message(conn, peer->cs, peer_msgin);
|
||||
return peer_read_message(conn, &peer->pcs, peer_msgin);
|
||||
|
||||
case WIRE_NODE_ANNOUNCEMENT:
|
||||
handle_node_announcement(peer->daemon->rstate, msg, tal_count(msg));
|
||||
return peer_read_message(conn, peer->cs, peer_msgin);
|
||||
return peer_read_message(conn, &peer->pcs, peer_msgin);
|
||||
|
||||
case WIRE_CHANNEL_UPDATE:
|
||||
handle_channel_update(peer->daemon->rstate, msg, tal_count(msg));
|
||||
return peer_read_message(conn, peer->cs, peer_msgin);
|
||||
return peer_read_message(conn, &peer->pcs, peer_msgin);
|
||||
|
||||
case WIRE_INIT:
|
||||
peer->error = "Duplicate INIT message received";
|
||||
@ -133,7 +134,7 @@ static struct io_plan *peer_msgin(struct io_conn *conn,
|
||||
case WIRE_REVOKE_AND_ACK:
|
||||
/* Not our place to handle this, so we punt */
|
||||
s = towire_gossipstatus_peer_nongossip(msg, peer->unique_id,
|
||||
peer->cs, msg);
|
||||
&peer->pcs.cs, msg);
|
||||
status_send(s);
|
||||
status_send_fd(io_conn_fd(conn));
|
||||
return io_close(conn);
|
||||
@ -147,7 +148,7 @@ static struct io_plan *peer_msgin(struct io_conn *conn,
|
||||
if (t & 1) {
|
||||
status_trace("Peer %"PRIu64" sent unknown packet %u, ignoring",
|
||||
peer->unique_id, t);
|
||||
return peer_read_message(conn, peer->cs, peer_msgin);
|
||||
return peer_read_message(conn, &peer->pcs, peer_msgin);
|
||||
}
|
||||
peer->error = tal_fmt(peer, "Unknown packet %u", t);
|
||||
return io_close(conn);
|
||||
@ -183,7 +184,8 @@ static struct io_plan *peer_dump_gossip(struct io_conn *conn, struct peer *peer)
|
||||
/* Going to wake up in pkt_out since we mix time based and message based wakeups */
|
||||
return io_out_wait(conn, peer, pkt_out, peer);
|
||||
} else {
|
||||
return peer_write_message(conn, peer->cs, next->payload, peer_dump_gossip);
|
||||
return peer_write_message(conn, &peer->pcs, next->payload,
|
||||
peer_dump_gossip);
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +198,7 @@ static struct io_plan *pkt_out(struct io_conn *conn, struct peer *peer)
|
||||
out = peer->msg_out[0];
|
||||
memmove(peer->msg_out, peer->msg_out + 1, (sizeof(*peer->msg_out)*(n-1)));
|
||||
tal_resize(&peer->msg_out, n-1);
|
||||
return peer_write_message(conn, peer->cs, out, pkt_out);
|
||||
return peer_write_message(conn, &peer->pcs, out, pkt_out);
|
||||
}
|
||||
|
||||
if (peer->gossip_sync){
|
||||
@ -259,13 +261,13 @@ static struct io_plan *peer_parse_init(struct io_conn *conn,
|
||||
/* Need to go duplex here, otherwise backpressure would mean
|
||||
* we both wait indefinitely */
|
||||
return io_duplex(conn,
|
||||
peer_read_message(conn, peer->cs, peer_msgin),
|
||||
peer_read_message(conn, &peer->pcs, peer_msgin),
|
||||
peer_dump_gossip(conn, peer));
|
||||
}
|
||||
|
||||
static struct io_plan *peer_init_sent(struct io_conn *conn, struct peer *peer)
|
||||
{
|
||||
return peer_read_message(conn, peer->cs, peer_parse_init);
|
||||
return peer_read_message(conn, &peer->pcs, peer_parse_init);
|
||||
}
|
||||
|
||||
static struct io_plan *peer_send_init(struct io_conn *conn, struct peer *peer)
|
||||
@ -278,7 +280,8 @@ static struct io_plan *peer_send_init(struct io_conn *conn, struct peer *peer)
|
||||
* SHOULD set feature bits corresponding to features it optionally
|
||||
* supports.
|
||||
*/
|
||||
return peer_write_message(conn, peer->cs, towire_init(peer, NULL, NULL),
|
||||
return peer_write_message(conn, &peer->pcs,
|
||||
towire_init(peer, NULL, NULL),
|
||||
peer_init_sent);
|
||||
}
|
||||
|
||||
@ -337,7 +340,7 @@ static struct io_plan *release_peer(struct io_conn *conn, struct daemon *daemon,
|
||||
|
||||
out = towire_gossipctl_release_peer_response(msg,
|
||||
unique_id,
|
||||
peer->cs);
|
||||
&peer->pcs.cs);
|
||||
return io_write_wire(conn, out, release_peer_fd, peer);
|
||||
}
|
||||
}
|
||||
|
@ -46,17 +46,16 @@ static void peer_nongossip(struct subdaemon *gossip, const u8 *msg, int fd)
|
||||
u64 unique_id;
|
||||
struct peer *peer;
|
||||
u8 *inner;
|
||||
struct crypto_state *cs = tal(msg, struct crypto_state);
|
||||
struct crypto_state cs;
|
||||
|
||||
if (!fromwire_gossipstatus_peer_nongossip(msg, msg, NULL,
|
||||
&unique_id, cs, &inner))
|
||||
&unique_id, &cs, &inner))
|
||||
fatal("Gossip gave bad PEER_NONGOSSIP message %s",
|
||||
tal_hex(msg, msg));
|
||||
|
||||
peer = peer_by_unique_id(gossip->ld, unique_id);
|
||||
if (!peer)
|
||||
fatal("Gossip gave bad peerid %"PRIu64, unique_id);
|
||||
cs->peer = peer;
|
||||
|
||||
log_debug(gossip->log, "Peer %s said %s",
|
||||
type_to_string(msg, struct pubkey, peer->id),
|
||||
|
@ -972,7 +972,7 @@ int main(int argc, char *argv[])
|
||||
struct pubkey my_id, their_id;
|
||||
int hsmfd = 3, clientfd = 4;
|
||||
struct secret ck, rk, sk;
|
||||
struct crypto_state *cs;
|
||||
struct crypto_state cs;
|
||||
|
||||
if (argc == 2 && streq(argv[1], "--version")) {
|
||||
printf("%s\n", version());
|
||||
@ -994,17 +994,23 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (fromwire_handshake_responder_req(msg, NULL, &my_id)) {
|
||||
responder(clientfd, &my_id, &their_id, &ck, &sk, &rk);
|
||||
cs = crypto_state(NULL, &sk.s, &rk.s, &ck.s, &ck.s, 0, 0);
|
||||
cs.rn = cs.sn = 0;
|
||||
cs.sk = sk.s;
|
||||
cs.rk = rk.s;
|
||||
cs.r_ck = cs.s_ck = ck.s;
|
||||
wire_sync_write(REQ_FD,
|
||||
towire_handshake_responder_resp(msg,
|
||||
&their_id,
|
||||
cs));
|
||||
&cs));
|
||||
} else if (fromwire_handshake_initiator_req(msg, NULL, &my_id,
|
||||
&their_id)) {
|
||||
initiator(clientfd, &my_id, &their_id, &ck, &sk, &rk);
|
||||
cs = crypto_state(NULL, &sk.s, &rk.s, &ck.s, &ck.s, 0, 0);
|
||||
cs.rn = cs.sn = 0;
|
||||
cs.sk = sk.s;
|
||||
cs.rk = rk.s;
|
||||
cs.r_ck = cs.s_ck = ck.s;
|
||||
wire_sync_write(REQ_FD,
|
||||
towire_handshake_initiator_resp(msg, cs));
|
||||
towire_handshake_initiator_resp(msg, &cs));
|
||||
} else
|
||||
status_failed(WIRE_HANDSHAKE_BAD_COMMAND, "%i", fromwire_peektype(msg));
|
||||
|
||||
|
@ -88,23 +88,22 @@ struct peer *peer_by_unique_id(struct lightningd *ld, u64 unique_id)
|
||||
static void handshake_succeeded(struct subdaemon *hs, const u8 *msg,
|
||||
struct peer *peer)
|
||||
{
|
||||
struct crypto_state *cs = tal(peer, struct crypto_state);
|
||||
struct crypto_state cs;
|
||||
|
||||
if (!peer->id) {
|
||||
struct pubkey id;
|
||||
|
||||
if (!fromwire_handshake_responder_resp(msg, NULL, &id, cs))
|
||||
if (!fromwire_handshake_responder_resp(msg, NULL, &id, &cs))
|
||||
goto err;
|
||||
peer->id = tal_dup(peer, struct pubkey, &id);
|
||||
log_info_struct(hs->log, "Peer in from %s",
|
||||
struct pubkey, peer->id);
|
||||
} else {
|
||||
if (!fromwire_handshake_initiator_resp(msg, NULL, cs))
|
||||
if (!fromwire_handshake_initiator_resp(msg, NULL, &cs))
|
||||
goto err;
|
||||
log_info_struct(hs->log, "Peer out to %s",
|
||||
struct pubkey, peer->id);
|
||||
}
|
||||
cs->peer = peer;
|
||||
|
||||
/* FIXME: Look for peer duplicates! */
|
||||
|
||||
@ -117,7 +116,7 @@ static void handshake_succeeded(struct subdaemon *hs, const u8 *msg,
|
||||
peer_set_condition(peer, "Beginning gossip");
|
||||
|
||||
/* Tell gossip to handle it now. */
|
||||
msg = towire_gossipctl_new_peer(msg, peer->unique_id, cs);
|
||||
msg = towire_gossipctl_new_peer(msg, peer->unique_id, &cs);
|
||||
subdaemon_req(peer->ld->gossip, msg, peer->fd, &peer->fd, NULL, NULL);
|
||||
|
||||
/* Peer struct longer owns fd. */
|
||||
|
@ -67,7 +67,7 @@ static struct sha256 sha256_from_hex(const char *hex)
|
||||
int main(void)
|
||||
{
|
||||
tal_t *tmpctx = tal_tmpctx(NULL);
|
||||
struct crypto_state *cs_out, *cs_in;
|
||||
struct peer_crypto_state cs_out, cs_in;
|
||||
struct sha256 sk, rk, ck;
|
||||
const void *msg = tal_dup_arr(tmpctx, char, "hello", 5, 0);
|
||||
size_t i;
|
||||
@ -89,13 +89,17 @@ int main(void)
|
||||
sk = sha256_from_hex("0x969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9");
|
||||
rk = sha256_from_hex("0xbb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442");
|
||||
|
||||
cs_out = crypto_state(tmpctx, &sk, &rk, &ck, &ck, 0, 0);
|
||||
cs_in = crypto_state(tmpctx, &rk, &sk, &ck, &ck, 0, 0);
|
||||
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(tmpctx, &cs_in);
|
||||
init_peer_crypto_state(tmpctx, &cs_out);
|
||||
|
||||
for (i = 0; i < 1002; i++) {
|
||||
write_buf = tal_arr(tmpctx, char, 0);
|
||||
|
||||
peer_write_message(NULL, cs_out, msg, check_msg_write);
|
||||
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));
|
||||
@ -104,7 +108,7 @@ int main(void)
|
||||
read_buf_len = tal_count(read_buf);
|
||||
write_buf = tal_arr(tmpctx, char, 0);
|
||||
|
||||
peer_read_message(NULL, cs_in, check_msg_read);
|
||||
peer_read_message(NULL, &cs_in, check_msg_read);
|
||||
assert(read_buf_len == 0);
|
||||
}
|
||||
tal_free(tmpctx);
|
||||
|
Loading…
Reference in New Issue
Block a user