lnsocket

A minimal C library for connecting to the lightning network
git clone git://jb55.com/lnsocket
Log | Files | Refs | Submodules | README | LICENSE

commit d67f1fe11add3c1c7eb626456f53751989787176
parent 1e25805c232b4cfb5e024ab3fcc5eb38fbdea8e4
Author: William Casarin <jb55@jb55.com>
Date:   Sun,  9 Jan 2022 17:08:53 -0800

more stuff

Diffstat:
A.gitmodules | 3+++
MMakefile | 22+++++++++++++++++++---
Adeps/secp256k1 | 1+
Ahandshake.h | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mnetln.c | 76++--------------------------------------------------------------------------
5 files changed, 132 insertions(+), 77 deletions(-)

diff --git a/.gitmodules b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "deps/secp256k1"] + path = deps/secp256k1 + url = https://github.com/bitcoin-core/secp256k1 diff --git a/Makefile b/Makefile @@ -1,12 +1,28 @@ -CFLAGS=-Wall -g -Og +CFLAGS=-Wall -g -Og -Ideps/secp256k1 + +LDFLAGS= all: netln -netln: netln.c - $(CC) $(CFLAGS) $^ -o $@ +deps/secp256k1/src/libsecp256k1-config.h: deps/secp256k1/configure + ./configure + +deps/secp256k1/configure: + cd deps/secp256k1; \ + ./autogen.sh + +deps/secp256k1/.libs/libsecp256k1.a: deps/secp256k1/configure + cd deps/secp256k1; \ + make -j2 libsecp256k1.la + +netln: netln.c deps/secp256k1/.libs/libsecp256k1.a + $(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@ clean: fake rm -f netln + cd deps/secp256k1; \ + make clean + .PHONY: fake diff --git a/deps/secp256k1 b/deps/secp256k1 @@ -0,0 +1 @@ +Subproject commit a1102b12196ea27f44d6201de4d25926a2ae9640 diff --git a/handshake.h b/handshake.h @@ -0,0 +1,107 @@ + +#ifndef LNLINK_HANDSHAKE_H +#define LNLINK_HANDSHAKE_H + +#include <secp256k1/> + +struct pubkey { + /* Unpacked pubkey (as used by libsecp256k1 internally) */ + secp256k1_pubkey pubkey; +}; + +/* BOLT #8: + * + * Act One is sent from initiator to responder. During Act One, the + * initiator attempts to satisfy an implicit challenge by the responder. To + * complete this challenge, the initiator must know the static public key of + * the responder. + */ +struct act_one { + u8 v; + u8 pubkey[PUBKEY_CMPR_LEN]; + u8 tag[crypto_aead_chacha20poly1305_ietf_ABYTES]; +}; + +/* BOLT #8: + * + * Act Two is sent from the responder to the initiator. Act Two will + * _only_ take place if Act One was successful. Act One was successful if + * the responder was able to properly decrypt and check the MAC of the tag + * sent at the end of Act One. + */ +struct act_two { + u8 v; + u8 pubkey[PUBKEY_CMPR_LEN]; + u8 tag[crypto_aead_chacha20poly1305_ietf_ABYTES]; +}; + +/* BOLT #8: + * + * Act Three is the final phase in the authenticated key agreement described + * in this section. This act is sent from the initiator to the responder as a + * concluding step. Act Three is executed _if and only if_ Act Two was + * successful. During Act Three, the initiator transports its static public + * key to the responder encrypted with _strong_ forward secrecy, using the + * accumulated `HKDF` derived secret key at this point of the handshake. + */ +struct act_three { + u8 v; + u8 ciphertext[PUBKEY_CMPR_LEN + crypto_aead_chacha20poly1305_ietf_ABYTES]; + u8 tag[crypto_aead_chacha20poly1305_ietf_ABYTES]; +}; + +/* BOLT #8: + * + * Throughout the handshake process, each side maintains these variables: + * + * * `ck`: the **chaining key**. This value is the accumulated hash of all + * previous ECDH outputs. At the end of the handshake, `ck` is used to derive + * the encryption keys for Lightning messages. + * + * * `h`: the **handshake hash**. This value is the accumulated hash of _all_ + * handshake data that has been sent and received so far during the handshake + * process. + * + * * `temp_k1`, `temp_k2`, `temp_k3`: the **intermediate keys**. These are used to + * encrypt and decrypt the zero-length AEAD payloads at the end of each handshake + * message. + * + * * `e`: a party's **ephemeral keypair**. For each session, a node MUST generate a + * new ephemeral key with strong cryptographic randomness. + * + * * `s`: a party's **static keypair** (`ls` for local, `rs` for remote) + */ +struct handshake { + struct secret ck; + struct secret temp_k; + struct sha256 h; + struct keypair e; + struct secret *ss; + + /* Used between the Acts */ + struct pubkey re; + struct act_one act1; + struct act_two act2; + struct act_three act3; + + /* Where is connection from/to */ + struct wireaddr_internal addr; + + /* Who we are */ + struct pubkey my_id; + /* Who they are: set already if we're initiator. */ + struct pubkey their_id; + + /* Are we initiator or responder. */ + enum bolt8_side side; + + /* Function to call once handshake complete. */ + struct io_plan *(*cb)(struct io_conn *conn, + const struct pubkey *their_id, + const struct wireaddr_internal *wireaddr, + struct crypto_state *cs, + void *cbarg); + void *cbarg; +}; + +#endif /* LNLINK_HANDSHAKE_H */ diff --git a/netln.c b/netln.c @@ -8,6 +8,8 @@ #include <string.h> #include <errno.h> +#include "handshake.h" + #define array_len(x) (sizeof(x)/sizeof(x[0])) struct netln { @@ -15,80 +17,6 @@ struct netln { int num_errors; }; - -struct pubkey { - /* Unpacked pubkey (as used by libsecp256k1 internally) */ - secp256k1_pubkey pubkey; -}; - -/* BOLT #8: - * - * Act One is sent from initiator to responder. During Act One, the - * initiator attempts to satisfy an implicit challenge by the responder. To - * complete this challenge, the initiator must know the static public key of - * the responder. - */ -struct act_one { - u8 v; - u8 pubkey[PUBKEY_CMPR_LEN]; - u8 tag[crypto_aead_chacha20poly1305_ietf_ABYTES]; -}; - -/* BOLT #8: - * - * Throughout the handshake process, each side maintains these variables: - * - * * `ck`: the **chaining key**. This value is the accumulated hash of all - * previous ECDH outputs. At the end of the handshake, `ck` is used to derive - * the encryption keys for Lightning messages. - * - * * `h`: the **handshake hash**. This value is the accumulated hash of _all_ - * handshake data that has been sent and received so far during the handshake - * process. - * - * * `temp_k1`, `temp_k2`, `temp_k3`: the **intermediate keys**. These are used to - * encrypt and decrypt the zero-length AEAD payloads at the end of each handshake - * message. - * - * * `e`: a party's **ephemeral keypair**. For each session, a node MUST generate a - * new ephemeral key with strong cryptographic randomness. - * - * * `s`: a party's **static keypair** (`ls` for local, `rs` for remote) - */ -struct handshake { - struct secret ck; - struct secret temp_k; - struct sha256 h; - struct keypair e; - struct secret *ss; - - /* Used between the Acts */ - struct pubkey re; - struct act_one act1; - struct act_two act2; - struct act_three act3; - - /* Where is connection from/to */ - struct wireaddr_internal addr; - - /* Who we are */ - struct pubkey my_id; - /* Who they are: set already if we're initiator. */ - struct pubkey their_id; - - /* Are we initiator or responder. */ - enum bolt8_side side; - - /* Function to call once handshake complete. */ - struct io_plan *(*cb)(struct io_conn *conn, - const struct pubkey *their_id, - const struct wireaddr_internal *wireaddr, - struct crypto_state *cs, - void *cbarg); - void *cbarg; -}; - - static void push_error(struct netln *netln, const char *err) { if (netln->num_errors >= array_len(netln->errors)) {