From ebba5f85a25ce5a9d4d7f2aeb9adc566c89114d4 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 11 Oct 2017 20:39:49 +1030 Subject: [PATCH] handshaked: remove. Signed-off-by: Rusty Russell --- Makefile | 1 - doc/HACKING.md | 2 - handshaked/Makefile | 71 -- handshaked/handshake.c | 1075 ------------------------------- handshaked/handshake_wire.csv | 31 - handshaked/test/.gitignore | 1 - handshaked/test/Makefile | 30 - handshaked/test/run-handshake.c | 163 ----- lightningd/.gitignore | 1 - lightningd/lightningd.c | 1 - 10 files changed, 1376 deletions(-) delete mode 100644 handshaked/Makefile delete mode 100644 handshaked/handshake.c delete mode 100644 handshaked/handshake_wire.csv delete mode 100644 handshaked/test/.gitignore delete mode 100644 handshaked/test/Makefile delete mode 100644 handshaked/test/run-handshake.c diff --git a/Makefile b/Makefile index c5795b2f7..287080500 100644 --- a/Makefile +++ b/Makefile @@ -144,7 +144,6 @@ include common/Makefile include wire/Makefile include wallet/Makefile include hsmd/Makefile -include handshaked/Makefile include gossipd/Makefile include openingd/Makefile include channeld/Makefile diff --git a/doc/HACKING.md b/doc/HACKING.md index fcbb18c59..5fb2bc351 100644 --- a/doc/HACKING.md +++ b/doc/HACKING.md @@ -61,8 +61,6 @@ Here's a list of parts, with notes: * hsmd/ - daemon which looks after the cryptographic secret, and performs commitment signing. -* handshaked/ - daemon to establish a single cryptographic handshake a-la BOLT 8. - * gossipd/ - daemon to chat to peers which don't have any channels, and maintains routing information and broadcasts gossip. * openingd/ - daemon to open a channel for a single peer. diff --git a/handshaked/Makefile b/handshaked/Makefile deleted file mode 100644 index e45d93f34..000000000 --- a/handshaked/Makefile +++ /dev/null @@ -1,71 +0,0 @@ -#! /usr/bin/make - -# Designed to be run one level up -handshaked-wrongdir: - $(MAKE) -C .. handshaked-all - -default: handshaked-all - -handshaked-all: lightningd/lightning_handshaked - -# handshaked needs these: -LIGHTNINGD_HANDSHAKE_HEADERS := \ - handshaked/gen_handshake_wire.h -LIGHTNINGD_HANDSHAKE_SRC := handshaked/handshake.c \ - $(LIGHTNINGD_HANDSHAKE_HEADERS:.h=.c) -LIGHTNINGD_HANDSHAKE_OBJS := $(LIGHTNINGD_HANDSHAKE_SRC:.c=.o) - -# Make sure these depend on everything. -ALL_OBJS += $(LIGHTNINGD_HANDSHAKE_OBJS) -ALL_PROGRAMS += lightningd/lightning_handshaked -ALL_GEN_HEADERS += $(LIGHTNINGD_HANDSHAKE_HEADERS) - -# Control daemon uses this: -LIGHTNINGD_HANDSHAKE_CONTROL_HEADERS := $(LIGHTNINGD_HANDSHAKE_HEADERS) -LIGHTNINGD_HANDSHAKE_CONTROL_SRC := $(LIGHTNINGD_HANDSHAKE_HEADERS:.h=.c) -LIGHTNINGD_HANDSHAKE_CONTROL_OBJS := $(LIGHTNINGD_HANDSHAKE_CONTROL_SRC:.c=.o) - -LIGHTNINGD_HANDSHAKE_GEN_SRC := $(filter handshaked/gen_%, $(LIGHTNINGD_HANDSHAKE_SRC) $(LIGHTNINGD_HANDSHAKE_CONTROL_SRC)) - -LIGHTNINGD_HANDSHAKE_SRC_NOGEN := $(filter-out handshaked/gen_%, $(LIGHTNINGD_HANDSHAKE_SRC)) - -# Add to headers which any object might need. -LIGHTNINGD_HEADERS_GEN += $(LIGHTNINGD_HANDSHAKE_HEADERS) - -$(LIGHTNINGD_HANDSHAKE_OBJS): $(LIGHTNINGD_HEADERS) - -# Common source we use. -HANDSHAKED_COMMON_OBJS := \ - common/crypto_state.o \ - common/crypto_sync.o \ - common/cryptomsg.o \ - common/daemon_conn.o \ - common/debug.o \ - common/dev_disconnect.o \ - common/msg_queue.o \ - common/status.o \ - common/type_to_string.o \ - common/utils.o \ - common/version.o - -handshaked/gen_handshake_wire.h: $(WIRE_GEN) handshaked/handshake_wire.csv - $(WIRE_GEN) --header $@ handshake_wire_type < handshaked/handshake_wire.csv > $@ - -handshaked/gen_handshake_wire.c: $(WIRE_GEN) handshaked/handshake_wire.csv - $(WIRE_GEN) ${@:.c=.h} handshake_wire_type < handshaked/handshake_wire.csv > $@ - -LIGHTNINGD_HANDSHAKE_OBJS := $(LIGHTNINGD_HANDSHAKE_SRC:.c=.o) $(LIGHTNINGD_HANDSHAKE_GEN_SRC:.c=.o) - -lightningd/lightning_handshaked: $(LIGHTNINGD_LIB_OBJS) $(LIGHTNINGD_HANDSHAKE_OBJS) $(HANDSHAKED_COMMON_OBJS) $(WIRE_OBJS) $(BITCOIN_OBJS) $(LIGHTNINGD_HSM_CLIENT_OBJS) - -check-source: $(LIGHTNINGD_HANDSHAKE_SRC_NOGEN:%=check-src-include-order/%) -check-source-bolt: $(LIGHTNINGD_HANDSHAKE_SRC:%=bolt-check/%) $(LIGHTNINGD_HANDSHAKE_HEADERS:%=bolt-check/%) - -check-whitespace: $(LIGHTNINGD_HANDSHAKE_SRC_NOGEN:%=check-whitespace/%) $(LIGHTNINGD_HANDSHAKE_HEADERS_NOGEN:%=check-whitespace/%) - -clean: handshaked-clean - -handshaked-clean: - $(RM) $(LIGHTNINGD_HANDSHAKE_OBJS) gen_* - --include handshaked/test/Makefile diff --git a/handshaked/handshake.c b/handshaked/handshake.c deleted file mode 100644 index 15f1ef4e9..000000000 --- a/handshaked/handshake.c +++ /dev/null @@ -1,1075 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define REQ_FD STDIN_FILENO - -/* BOLT #8: - * - * * `generateKey()` - * * where generateKey generates and returns a fresh `secp256k1` keypair - * * the object returned by `generateKey` has two attributes: - * * `.pub`: which returns an abstract object representing the - * public key - * * `.priv`: which represents the private key used to generate the - * public key - */ -struct keypair { - struct pubkey pub; - struct privkey priv; -}; - -static struct keypair generate_key(void) -{ - struct keypair k; - - do { - randombytes_buf(k.priv.secret.data, sizeof(k.priv.secret.data)); - } while (!secp256k1_ec_pubkey_create(secp256k1_ctx, - &k.pub.pubkey, k.priv.secret.data)); - return k; -} - -/* 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`: **intermediate keys** used to - * encrypt/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 public key** (`ls` for local, `rs` for remote) - */ -struct handshake { - struct secret ck; - struct secret temp_k; - struct sha256 h; - struct keypair e; - struct secret ss; -}; - -/* h = SHA-256(h || data) */ -static void sha_mix_in(struct sha256 *h, const void *data, size_t len) -{ - struct sha256_ctx shactx; - - sha256_init(&shactx); - sha256_update(&shactx, h, sizeof(*h)); - sha256_update(&shactx, data, len); - sha256_done(&shactx, h); -} - -/* h = SHA-256(h || pub.serializeCompressed()) */ -static void sha_mix_in_key(struct sha256 *h, const struct pubkey *key) -{ - u8 der[PUBKEY_DER_LEN]; - size_t len = sizeof(der); - - secp256k1_ec_pubkey_serialize(secp256k1_ctx, der, &len, &key->pubkey, - SECP256K1_EC_COMPRESSED); - assert(len == sizeof(der)); - sha_mix_in(h, der, sizeof(der)); -} - -/* out1, out2 = HKDF(in1, in2)` */ -static void hkdf_two_keys(struct secret *out1, struct secret *out2, - const struct secret *in1, - const void *in2, size_t in2_size) -{ - /* BOLT #8: - * - * * `HKDF(salt,ikm)`: a function is defined in [3](#reference-3), - * evaluated with a zero-length `info` field. - * * All invocations of the `HKDF` implicitly return `64-bytes` - * of cryptographic randomness using the extract-and-expand - * component of the `HKDF`. - */ - struct secret okm[2]; - - status_trace("# HKDF(0x%s,%s%s)", - tal_hexstr(trc, in1, sizeof(*in1)), - in2_size ? "0x" : "zero", - tal_hexstr(trc, in2, in2_size)); - BUILD_ASSERT(sizeof(okm) == 64); - hkdf_sha256(okm, sizeof(okm), in1, sizeof(*in1), in2, in2_size, - NULL, 0); - *out1 = okm[0]; - *out2 = okm[1]; -} - -static void le64_nonce(unsigned char *npub, u64 nonce) -{ - /* BOLT #8: - * - * ...with nonce `n` encoded as 32 zero bits followed by a - * *little-endian* 64-bit value (this follows the Noise Protocol - * convention, rather than our normal endian). - */ - le64 le_nonce = cpu_to_le64(nonce); - const size_t zerolen = crypto_aead_chacha20poly1305_ietf_NPUBBYTES - sizeof(le_nonce); - - BUILD_ASSERT(crypto_aead_chacha20poly1305_ietf_NPUBBYTES >= sizeof(le_nonce)); - /* First part is 0, followed by nonce. */ - memset(npub, 0, zerolen); - memcpy(npub + zerolen, &le_nonce, sizeof(le_nonce)); -} - -/* BOLT #8: - * * `encryptWithAD(k, n, ad, plaintext)`: outputs `encrypt(k, n, ad, - * plaintext)` - * * where `encrypt` is an evaluation of `ChaCha20-Poly1305` (IETF - * variant) with the passed arguments, with nonce `n` - */ -static void encrypt_ad(const struct secret *k, u64 nonce, - const void *additional_data, size_t additional_data_len, - const void *plaintext, size_t plaintext_len, - void *output, size_t outputlen) -{ - unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES]; - unsigned long long clen; - int ret; - - assert(outputlen == plaintext_len + crypto_aead_chacha20poly1305_ietf_ABYTES); - le64_nonce(npub, nonce); - BUILD_ASSERT(sizeof(*k) == crypto_aead_chacha20poly1305_ietf_KEYBYTES); - status_trace("# encryptWithAD(0x%s, 0x%s, 0x%s, %s%s)", - tal_hexstr(trc, k, sizeof(*k)), - tal_hexstr(trc, npub, sizeof(npub)), - tal_hexstr(trc, additional_data, additional_data_len), - plaintext_len ? "0x" : "", - tal_hexstr(trc, plaintext, plaintext_len)); - - ret = crypto_aead_chacha20poly1305_ietf_encrypt(output, &clen, - memcheck(plaintext, plaintext_len), - plaintext_len, - additional_data, additional_data_len, - NULL, npub, k->data); - assert(ret == 0); - assert(clen == plaintext_len + crypto_aead_chacha20poly1305_ietf_ABYTES); -} - -/* BOLT #8: - * * `decryptWithAD(k, n, ad, ciphertext)`: outputs `decrypt(k, n, ad, - * ciphertext)` - * * where `decrypt` is an evaluation of `ChaCha20-Poly1305` (IETF - * variant) with the passed arguments, with nonce `n` - */ -static bool decrypt(const struct secret *k, u64 nonce, - const void *additional_data, size_t additional_data_len, - const void *ciphertext, size_t ciphertext_len, - void *output, size_t outputlen) -{ - unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES]; - unsigned long long mlen; - - assert(outputlen == ciphertext_len - crypto_aead_chacha20poly1305_ietf_ABYTES); - - le64_nonce(npub, nonce); - BUILD_ASSERT(sizeof(*k) == crypto_aead_chacha20poly1305_ietf_KEYBYTES); - status_trace("# decryptWithAD(0x%s, 0x%s, 0x%s, 0x%s)", - tal_hexstr(trc, k, sizeof(*k)), - tal_hexstr(trc, npub, sizeof(npub)), - tal_hexstr(trc, additional_data, additional_data_len), - tal_hexstr(trc, ciphertext, ciphertext_len)); - if (crypto_aead_chacha20poly1305_ietf_decrypt(output, &mlen, NULL, - memcheck(ciphertext, ciphertext_len), - ciphertext_len, - additional_data, additional_data_len, - npub, k->data) != 0) - return false; - - assert(mlen == ciphertext_len - crypto_aead_chacha20poly1305_ietf_ABYTES); - return true; -} - -static struct handshake *new_handshake(const tal_t *ctx, - const struct pubkey *id) -{ - struct handshake *handshake = tal(ctx, struct handshake); - - /* BOLT #8: - * - * Before the start of the first act, both sides initialize their - * per-sessions state as follows: - * - * 1. `h = SHA-256(protocolName)` - * * where `protocolName = "Noise_XK_secp256k1_ChaChaPoly_SHA256"` - * encoded as an ASCII string. - */ - sha256(&handshake->h, "Noise_XK_secp256k1_ChaChaPoly_SHA256", - strlen("Noise_XK_secp256k1_ChaChaPoly_SHA256")); - - /* BOLT #8: - * - * 2. `ck = h` - */ - BUILD_ASSERT(sizeof(handshake->h) == sizeof(handshake->ck)); - memcpy(&handshake->ck, &handshake->h, sizeof(handshake->ck)); - status_trace("# ck=%s", - tal_hexstr(trc, &handshake->ck, sizeof(handshake->ck))); - - /* BOLT #8: - * - * 3. `h = SHA-256(h || prologue)` - * * where `prologue` is the ASCII string: `lightning`. - */ - sha_mix_in(&handshake->h, "lightning", strlen("lightning")); - - /* BOLT #8: - * - * As a concluding step, both sides mix the responder's public key - * into the handshake digest: - * - * * The initiating node mixes in the responding node's static public - * key serialized in Bitcoin's DER compressed format: - * * `h = SHA-256(h || rs.pub.serializeCompressed())` - * - * * The responding node mixes in their local static public key - * serialized in Bitcoin's DER compressed format: - * * `h = SHA-256(h || ls.pub.serializeCompressed())` - */ - sha_mix_in_key(&handshake->h, id); - status_trace("# h=%s", - tal_hexstr(trc, &handshake->h, sizeof(handshake->h))); - - return handshake; -} - -/* 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_DER_LEN]; - u8 tag[crypto_aead_chacha20poly1305_ietf_ABYTES]; -}; - -/* BOLT #8: The handshake message is _exactly_ `50 bytes` */ -#define ACT_ONE_SIZE 50 /* ARM's stupid ABI adds padding. */ - -static inline void check_act_one(const struct act_one *act1) -{ - /* BOLT #8: - * - * : `1 byte` for the handshake version, `33 bytes` for the compressed - * ephemeral public key of the initiator, and `16 bytes` for the - * `poly1305` tag. - */ - BUILD_ASSERT(sizeof(act1->v) == 1); - BUILD_ASSERT(sizeof(act1->pubkey) == 33); - BUILD_ASSERT(sizeof(act1->tag) == 16); -} - -static void act_one_initiator(struct handshake *h, int fd, - const struct pubkey *their_id) -{ - struct act_one act1; - size_t len; - - status_send_sync(towire_initr_act_one(h)); - - /* BOLT #8: - * - * **Sender Actions:** - * - * * `e = generateKey()` - */ - h->e = generate_key(); - status_trace("e.priv: 0x%s", - tal_hexstr(trc, &h->e.priv, sizeof(h->e.priv))); - status_trace("e.pub: 0x%s", - type_to_string(trc, struct pubkey, &h->e.pub)); - - /* BOLT #8: - * - * * `h = SHA-256(h || e.pub.serializeCompressed())` - * * The newly generated ephemeral key is accumulated into our - * running handshake digest. - */ - sha_mix_in_key(&h->h, &h->e.pub); - status_trace("# h=0x%s", tal_hexstr(trc, &h->h, sizeof(h->h))); - - /* BOLT #8: - * - * * `ss = ECDH(rs, e.priv)` - * * The initiator performs a `ECDH` between its newly generated - * ephemeral key with the remote node's static public key. - */ - if (!secp256k1_ecdh(secp256k1_ctx, h->ss.data, - &their_id->pubkey, h->e.priv.secret.data)) - status_failed(STATUS_FAIL_PEER_BAD, - "WIRE_INITR_ACT1_BAD_ECDH_FOR_SS: %s", ""); - status_trace("# ss=0x%s", tal_hexstr(trc, h->ss.data, sizeof(h->ss.data))); - - /* BOLT #8: - * - * * `ck, temp_k1 = HKDF(ck, ss)` - * * This phase generates a new temporary encryption key - * which is used to generate the authenticating MAC. - */ - hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, &h->ss, sizeof(h->ss)); - status_trace("# ck,temp_k1=0x%s,0x%s", - tal_hexstr(trc, &h->ck, sizeof(h->ck)), - tal_hexstr(trc, &h->temp_k, sizeof(h->temp_k))); - - /* BOLT #8: - * - * * `c = encryptWithAD(temp_k1, 0, h, zero)` - * * where `zero` is a zero-length plaintext - */ - encrypt_ad(&h->temp_k, 0, &h->h, sizeof(h->h), NULL, 0, - act1.tag, sizeof(act1.tag)); - status_trace("# c=%s", tal_hexstr(trc, act1.tag, sizeof(act1.tag))); - - /* BOLT #8: - * - * * `h = SHA-256(h || c)` - * * Finally, the generated ciphertext is accumulated into the - * authenticating handshake digest. - */ - sha_mix_in(&h->h, act1.tag, sizeof(act1.tag)); - status_trace("# h=0x%s", tal_hexstr(trc, &h->h, sizeof(h->h))); - - /* BOLT #8: - * - * * Send `m = 0 || e.pub.serializeCompressed() || c` to the responder over the network buffer. - */ - act1.v = 0; - len = sizeof(act1.pubkey); - secp256k1_ec_pubkey_serialize(secp256k1_ctx, act1.pubkey, &len, - &h->e.pub.pubkey, - SECP256K1_EC_COMPRESSED); - status_trace("output: 0x%s", tal_hexstr(trc, &act1, ACT_ONE_SIZE)); - if (!write_all(fd, &act1, ACT_ONE_SIZE)) - status_failed(STATUS_FAIL_PEER_IO, - "WIRE_INITR_ACT1_WRITE_FAILED: %s", - strerror(errno)); -} - -static void act_one_responder(struct handshake *h, int fd, struct pubkey *re) -{ - struct act_one act1; - - status_send_sync(towire_respr_act_one(h)); - - /* BOLT #8: - * - * * Read _exactly_ `50-bytes` from the network buffer. - * - * * Parse out the read message (`m`) into `v = m[0]`, `re = - * m[1:33]` and `c = m[34:]` - * * where `m[0]` is the _first_ byte of `m`, `m[1:33]` are the - * next `33` bytes of `m` and `m[34:]` is the last 16 bytes of - * `m` - */ - if (!read_all(fd, &act1, ACT_ONE_SIZE)) - status_failed(STATUS_FAIL_PEER_IO, - "WIRE_RESPR_ACT1_READ_FAILED: %s", - strerror(errno)); - status_trace("input: 0x%s", tal_hexstr(trc, &act1, ACT_ONE_SIZE)); - - /* BOLT #8: - * - * * If `v` is an unrecognized handshake version, then the responder - * MUST abort the connection attempt. - */ - if (act1.v != 0) - status_failed(STATUS_FAIL_PEER_BAD, - "WIRE_RESPR_ACT1_BAD_VERSION: %u", act1.v); - - /* BOLT #8: - * * The raw bytes of the remote party's ephemeral public key - * (`e`) are to be deserialized into a point on the curve using - * affine coordinates as encoded by the key's serialized - * composed format. - */ - if (secp256k1_ec_pubkey_parse(secp256k1_ctx, &re->pubkey, - act1.pubkey, sizeof(act1.pubkey)) != 1) - status_failed(STATUS_FAIL_PEER_BAD, - "WIRE_RESPR_ACT1_BAD_PUBKEY: %s", - tal_hexstr(trc, &act1.pubkey, - sizeof(act1.pubkey))); - status_trace("# re=0x%s", type_to_string(trc, struct pubkey, re)); - - /* BOLT #8: - * - * * `h = SHA-256(h || re.serializeCompressed())` - * * Accumulate the initiator's ephemeral key into the - * authenticating handshake digest. - */ - sha_mix_in_key(&h->h, re); - status_trace("# h=0x%s", tal_hexstr(trc, &h->h, sizeof(h->h))); - - /* BOLT #8: - * * `ss = ECDH(re, s.priv)` - * * The responder performs an `ECDH` between its static public - * key and the initiator's ephemeral public key. - */ - if (!hsm_do_ecdh(&h->ss, re)) - status_failed(STATUS_FAIL_PEER_BAD, - "WIRE_RESPR_ACT1_BAD_HSM_ECDH: re=%s", - type_to_string(trc, struct pubkey, re)); - status_trace("# ss=0x%s", tal_hexstr(trc, &h->ss, sizeof(h->ss))); - - /* BOLT #8: - * - * * `ck, temp_k1 = HKDF(ck, ss)` - * * This phase generates a new temporary encryption key - * which will be used to shortly check the - * authenticating MAC. - */ - hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, &h->ss, sizeof(h->ss)); - status_trace("# ck,temp_k1=0x%s,0x%s", - tal_hexstr(trc, &h->ck, sizeof(h->ck)), - tal_hexstr(trc, &h->temp_k, sizeof(h->temp_k))); - - /* BOLT #8: - * - * * `p = decryptWithAD(temp_k1, 0, h, c)` - * * If the MAC check in this operation fails, then the initiator - * does _not_ know our static public key. If so, then the - * responder MUST terminate the connection without any further - * messages. - */ - if (!decrypt(&h->temp_k, 0, &h->h, sizeof(h->h), - act1.tag, sizeof(act1.tag), NULL, 0)) - status_failed(STATUS_FAIL_PEER_BAD, - "WIRE_RESPR_ACT1_BAD_TAG: re=%s ss=%s tag=%s", - type_to_string(trc, struct pubkey, re), - tal_hexstr(trc, &h->ss, sizeof(h->ss)), - tal_hexstr(trc, act1.tag, sizeof(act1.tag))); - - /* BOLT #8: - * - * * `h = SHA-256(h || c)` - * * Mix the received ciphertext into the handshake digest. This - * step serves to ensure the payload wasn't modified by a MiTM. - */ - sha_mix_in(&h->h, act1.tag, sizeof(act1.tag)); - status_trace("# h=0x%s", tal_hexstr(trc, &h->h, sizeof(h->h))); -} - -/* 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_DER_LEN]; - u8 tag[crypto_aead_chacha20poly1305_ietf_ABYTES]; -}; - -/* BOLT #8: The handshake is _exactly_ `50 bytes:` */ -#define ACT_TWO_SIZE 50 /* ARM's stupid ABI adds padding. */ - -static inline void check_act_two(const struct act_two *act2) -{ - /* BOLT #8: - * `1 byte` for the handshake version, - * `33 bytes` for the compressed ephemeral public key of the initiator, and - * `16 bytes` for the `poly1305` tag. - */ - BUILD_ASSERT(sizeof(act2->v) == 1); - BUILD_ASSERT(sizeof(act2->pubkey) == 33); - BUILD_ASSERT(sizeof(act2->tag) == 16); -} - -static void act_two_responder(struct handshake *h, int fd, - const struct pubkey *re) -{ - struct act_two act2; - size_t len; - - status_send_sync(towire_respr_act_two(h)); - - /* BOLT #8: - * - * **Sender Actions:** - * - * * `e = generateKey()` - */ - h->e = generate_key(); - status_trace("# e.pub=0x%s e.priv=0x%s", - type_to_string(trc, struct pubkey, &h->e.pub), - tal_hexstr(trc, &h->e.priv, sizeof(h->e.priv))); - - /* BOLT #8: - * - * * `h = SHA-256(h || e.pub.serializeCompressed())` - * * The newly generated ephemeral key is accumulated into our - * running handshake digest. - */ - sha_mix_in_key(&h->h, &h->e.pub); - status_trace("# h=0x%s", tal_hexstr(trc, &h->h, sizeof(h->h))); - - /* BOLT #8: - * - * * `ss = ECDH(re, e.priv)` - * * where `re` is the ephemeral key of the initiator which was - * received during `ActOne`. - */ - if (!secp256k1_ecdh(secp256k1_ctx, h->ss.data, &re->pubkey, - h->e.priv.secret.data)) - status_failed(STATUS_FAIL_PEER_BAD, - "WIRE_RESPR_ACT2_BAD_ECDH_FOR_SS: re=%s e.priv=%s", - type_to_string(trc, struct pubkey, re), - tal_hexstr(trc, &h->e.priv, sizeof(h->e.priv))); - status_trace("# ss=0x%s", tal_hexstr(trc, &h->ss, sizeof(h->ss))); - - /* BOLT #8: - * - * * `ck, temp_k2 = HKDF(ck, ss)` - * * This phase generates a new temporary encryption key - * which is used to generate the authenticating MAC. - */ - hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, &h->ss, sizeof(h->ss)); - status_trace("# ck,temp_k2=0x%s,0x%s", - tal_hexstr(trc, &h->ck, sizeof(h->ck)), - tal_hexstr(trc, &h->temp_k, sizeof(h->temp_k))); - - /* BOLT #8: - * - * * `c = encryptWithAD(temp_k2, 0, h, zero)` - * * where `zero` is a zero-length plaintext - */ - encrypt_ad(&h->temp_k, 0, &h->h, sizeof(h->h), NULL, 0, - act2.tag, sizeof(act2.tag)); - status_trace("# c=0x%s", tal_hexstr(trc, act2.tag, sizeof(act2.tag))); - - /* BOLT #8: - * - * * `h = SHA-256(h || c)` - * * Finally, the generated ciphertext is accumulated into the - * authenticating handshake digest. - */ - sha_mix_in(&h->h, act2.tag, sizeof(act2.tag)); - status_trace("# h=0x%s", tal_hexstr(trc, &h->h, sizeof(h->h))); - - /* BOLT #8: - * - * * Send `m = 0 || e.pub.serializeCompressed() || c` to the initiator over the network buffer. - */ - act2.v = 0; - len = sizeof(act2.pubkey); - secp256k1_ec_pubkey_serialize(secp256k1_ctx, act2.pubkey, &len, - &h->e.pub.pubkey, - SECP256K1_EC_COMPRESSED); - status_trace("output: 0x%s", tal_hexstr(trc, &act2, ACT_TWO_SIZE)); - if (!write_all(fd, &act2, ACT_TWO_SIZE)) - status_failed(STATUS_FAIL_PEER_IO, - "WIRE_RESPR_ACT2_WRITE_FAILED: %s", - strerror(errno)); -} - -static void act_two_initiator(struct handshake *h, int fd, struct pubkey *re) -{ - struct act_two act2; - - status_send_sync(towire_initr_act_two(h)); - - /* BOLT #8: - * - * * Read _exactly_ `50-bytes` from the network buffer. - * - * * Parse out the read message (`m`) into `v = m[0]`, `re = m[1:33]` - * and `c = m[34:]` - * * where `m[0]` is the _first_ byte of `m`, `m[1:33]` are the - * next `33` bytes of `m` and `m[34:]` is the last 16 bytes of - * `m` - */ - if (!read_all(fd, &act2, ACT_TWO_SIZE)) - status_failed(STATUS_FAIL_PEER_IO, - "WIRE_INITR_ACT2_READ_FAILED: %s", - strerror(errno)); - status_trace("input: 0x%s", tal_hexstr(trc, &act2, ACT_TWO_SIZE)); - - /* BOLT #8: - * - * * If `v` is an unrecognized handshake version, then the responder - * MUST abort the connection attempt. - */ - if (act2.v != 0) - status_failed(STATUS_FAIL_PEER_BAD, - "WIRE_INITR_ACT2_BAD_VERSION: %u", act2.v); - - /* BOLT #8: - * - * * The raw bytes of the remote party's ephemeral public key - * (`re`) are to be deserialized into a point on the curve using - * affine coordinates as encoded by the key's serialized - * composed format. - */ - if (secp256k1_ec_pubkey_parse(secp256k1_ctx, &re->pubkey, - act2.pubkey, sizeof(act2.pubkey)) != 1) - status_failed(STATUS_FAIL_PEER_BAD, - "WIRE_INITR_ACT2_BAD_PUBKEY: %s", - tal_hexstr(trc, &act2.pubkey, - sizeof(act2.pubkey))); - status_trace("# re=0x%s", type_to_string(trc, struct pubkey, re)); - - /* BOLT #8: - * - * * `h = SHA-256(h || re.serializeCompressed())` - */ - sha_mix_in_key(&h->h, re); - status_trace("# h=0x%s", tal_hexstr(trc, &h->h, sizeof(h->h))); - - /* BOLT #8: - * - * * `ss = ECDH(re, e.priv)` - */ - if (!secp256k1_ecdh(secp256k1_ctx, h->ss.data, &re->pubkey, - h->e.priv.secret.data)) - status_failed(STATUS_FAIL_PEER_BAD, - "WIRE_INITR_ACT2_BAD_ECDH_FOR_SS: re=%s e.priv=%s", - type_to_string(trc, struct pubkey, re), - tal_hexstr(trc, &h->e.priv, sizeof(h->e.priv))); - status_trace("# ss=0x%s", tal_hexstr(trc, &h->ss, sizeof(h->ss))); - - /* BOLT #8: - * - * * `ck, temp_k2 = HKDF(ck, ss)` - * * This phase generates a new temporary encryption key - * which is used to generate the authenticating MAC. - */ - hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, &h->ss, sizeof(h->ss)); - status_trace("# ck,temp_k2=0x%s,0x%s", - tal_hexstr(trc, &h->ck, sizeof(h->ck)), - tal_hexstr(trc, &h->temp_k, sizeof(h->temp_k))); - - /* BOLT #8: - * - * * `p = decryptWithAD(temp_k2, 0, h, c)` - * * If the MAC check in this operation fails, then the initiator - * MUST terminate the connection without any further messages. - */ - if (!decrypt(&h->temp_k, 0, &h->h, sizeof(h->h), - act2.tag, sizeof(act2.tag), NULL, 0)) - status_failed(STATUS_FAIL_PEER_BAD, - "WIRE_INITR_ACT2_BAD_TAG: c=%s", - tal_hexstr(trc, act2.tag, sizeof(act2.tag))); - - /* BOLT #8: - * - * * `h = SHA-256(h || c)` - * * Mix the received ciphertext into the handshake digest. This - * step serves to ensure the payload wasn't modified by a MiTM. - */ - sha_mix_in(&h->h, act2.tag, sizeof(act2.tag)); - status_trace("# h=0x%s", tal_hexstr(trc, &h->h, sizeof(h->h))); -} - -/* 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 - * final concluding step. `Act Three` is only executed `iff` `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_DER_LEN + crypto_aead_chacha20poly1305_ietf_ABYTES]; - u8 tag[crypto_aead_chacha20poly1305_ietf_ABYTES]; -}; - -/* BOLT #8: The handshake is _exactly_ `66 bytes` */ -#define ACT_THREE_SIZE 66 /* ARM's stupid ABI adds padding. */ - -static inline void check_act_three(const struct act_three *act3) -{ - /* BOLT #8: - * - * `1 byte` for the handshake version, `33 bytes` for the ephemeral - * public key encrypted with the `ChaCha20` stream cipher, `16 bytes` - * for the encrypted public key's tag generated via the `AEAD` - * construction, and `16 bytes` for a final authenticating tag. - */ - BUILD_ASSERT(sizeof(act3->v) == 1); - BUILD_ASSERT(sizeof(act3->ciphertext) == 33 + 16); - BUILD_ASSERT(sizeof(act3->tag) == 16); -} - -static void act_three_initiator(struct handshake *h, int fd, - const struct pubkey *re, - const struct pubkey *my_id) -{ - struct act_three act3; - u8 spub[PUBKEY_DER_LEN]; - size_t len = sizeof(spub); - - status_send_sync(towire_initr_act_three(h)); - - /* BOLT #8: - * * `c = encryptWithAD(temp_k2, 1, h, s.pub.serializeCompressed())` - * * where `s` is the static public key of the initiator. - */ - secp256k1_ec_pubkey_serialize(secp256k1_ctx, spub, &len, - &my_id->pubkey, - SECP256K1_EC_COMPRESSED); - encrypt_ad(&h->temp_k, 1, &h->h, sizeof(h->h), spub, sizeof(spub), - act3.ciphertext, sizeof(act3.ciphertext)); - status_trace("# c=0x%s", - tal_hexstr(trc,act3.ciphertext,sizeof(act3.ciphertext))); - - /* BOLT #8: - * * `h = SHA-256(h || c)` - */ - sha_mix_in(&h->h, act3.ciphertext, sizeof(act3.ciphertext)); - status_trace("# h=0x%s", tal_hexstr(trc, &h->h, sizeof(h->h))); - - /* BOLT #8: - * - * * `ss = ECDH(re, s.priv)` - * * where `re` is the ephemeral public key of the responder. - * - */ - if (!hsm_do_ecdh(&h->ss, re)) - status_failed(STATUS_FAIL_PEER_BAD, - "WIRE_INITR_ACT3_BAD_HSM_ECDH: re=%s", - type_to_string(trc, struct pubkey, re)); - status_trace("# ss=0x%s", tal_hexstr(trc, &h->ss, sizeof(h->ss))); - - /* BOLT #8: - * - * * `ck, temp_k3 = HKDF(ck, ss)` - * * Mix the final intermediate shared secret into the running chaining key. - */ - hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, &h->ss, sizeof(h->ss)); - status_trace("# ck,temp_k3=0x%s,0x%s", - tal_hexstr(trc, &h->ck, sizeof(h->ck)), - tal_hexstr(trc, &h->temp_k, sizeof(h->temp_k))); - - /* BOLT #8: - * - * * `t = encryptWithAD(temp_k3, 0, h, zero)` - * * where `zero` is a zero-length plaintext - * - */ - encrypt_ad(&h->temp_k, 0, &h->h, sizeof(h->h), NULL, 0, - act3.tag, sizeof(act3.tag)); - status_trace("# t=0x%s", - tal_hexstr(trc, act3.tag, sizeof(act3.tag))); - - /* BOLT #8: - * - * * Send `m = 0 || c || t` over the network buffer. - * - */ - act3.v = 0; - - status_trace("output: 0x%s", tal_hexstr(trc, &act3, ACT_THREE_SIZE)); - if (!write_all(fd, &act3, ACT_THREE_SIZE)) - status_failed(STATUS_FAIL_PEER_IO, - "WIRE_INITR_ACT3_WRITE_FAILED: %s", - strerror(errno)); -} - -static void act_three_responder(struct handshake *h, int fd, - struct pubkey *their_id) -{ - struct act_three act3; - u8 der[PUBKEY_DER_LEN]; - - status_send_sync(towire_respr_act_three(h)); - - /* BOLT #8: - * - * **Receiver Actions:** - * - * * Read _exactly_ `66-bytes` from the network buffer. - */ - if (!read_all(fd, &act3, ACT_THREE_SIZE)) - status_failed(STATUS_FAIL_PEER_IO, - "WIRE_RESPR_ACT3_READ_FAILED: %s", - strerror(errno)); - status_trace("input: 0x%s", tal_hexstr(trc, &act3, ACT_THREE_SIZE)); - - /* BOLT #8: - * - * * Parse out the read message (`m`) into `v = m[0]`, `c = m[1:49]` and `t = m[50:]` - */ - - /* BOLT #8: - * - * * If `v` is an unrecognized handshake version, then the responder MUST - * abort the connection attempt. - */ - if (act3.v != 0) - status_failed(STATUS_FAIL_PEER_BAD, - "WIRE_RESPR_ACT3_BAD_VERSION: %u", act3.v); - - /* BOLT #8: - * - * * `rs = decryptWithAD(temp_k2, 1, h, c)` - * * At this point, the responder has recovered the static public key of the - * initiator. - */ - if (!decrypt(&h->temp_k, 1, &h->h, sizeof(h->h), - act3.ciphertext, sizeof(act3.ciphertext), - der, sizeof(der))) - status_failed(STATUS_FAIL_PEER_BAD, - "WIRE_RESPR_ACT3_BAD_CIPHERTEXT: ciphertext=%s", - tal_hexstr(trc, act3.ciphertext, - sizeof(act3.ciphertext))); - status_trace("# rs=0x%s", tal_hexstr(trc, der, sizeof(der))); - - if (secp256k1_ec_pubkey_parse(secp256k1_ctx, &their_id->pubkey, - der, sizeof(der)) != 1) - status_failed(STATUS_FAIL_PEER_BAD, - "WIRE_RESPR_ACT3_BAD_PUBKEY: %s", - tal_hexstr(trc, &der, sizeof(der))); - - /* BOLT #8: - * - * * `h = SHA-256(h || c)` - * - */ - sha_mix_in(&h->h, act3.ciphertext, sizeof(act3.ciphertext)); - status_trace("# h=0x%s", tal_hexstr(trc, &h->h, sizeof(h->h))); - - /* BOLT #8: - * - * * `ss = ECDH(rs, e.priv)` - * * where `e` is the responder's original ephemeral key - */ - if (!secp256k1_ecdh(secp256k1_ctx, h->ss.data, &their_id->pubkey, - h->e.priv.secret.data)) - status_failed(STATUS_FAIL_PEER_BAD, - "WIRE_RESPR_ACT3_BAD_ECDH_FOR_SS: rs=%s e.priv=%s", - type_to_string(trc, struct pubkey, their_id), - tal_hexstr(trc, &h->e.priv, sizeof(h->e.priv))); - status_trace("# ss=0x%s", tal_hexstr(trc, &h->ss, sizeof(h->ss))); - - /* BOLT #8: - * * `ck, temp_k3 = HKDF(ck, ss)` - */ - hkdf_two_keys(&h->ck, &h->temp_k, &h->ck, &h->ss, sizeof(h->ss)); - status_trace("# ck,temp_k3=0x%s,0x%s", - tal_hexstr(trc, &h->ck, sizeof(h->ck)), - tal_hexstr(trc, &h->temp_k, sizeof(h->temp_k))); - - /* BOLT #8: - * * `p = decryptWithAD(temp_k3, 0, h, t)` - * * If the MAC check in this operation fails, then the responder MUST - * terminate the connection without any further messages. - * - */ - if (!decrypt(&h->temp_k, 0, &h->h, sizeof(h->h), - act3.tag, sizeof(act3.tag), NULL, 0)) - status_failed(STATUS_FAIL_PEER_BAD, - "WIRE_RESPR_ACT3_BAD_TAG: temp_k3=%s h=%s t=%s", - tal_hexstr(trc, &h->temp_k, sizeof(h->temp_k)), - tal_hexstr(trc, &h->h, sizeof(h->h)), - tal_hexstr(trc, act3.tag, sizeof(act3.tag))); -} - -static void initiator(int fd, const struct pubkey *my_id, - const struct pubkey *their_id, - struct secret *ck, struct secret *sk, struct secret *rk) -{ - const tal_t *tmpctx = tal_tmpctx(NULL); - struct handshake *h = new_handshake(tmpctx, their_id); - struct pubkey re; - - act_one_initiator(h, fd, their_id); - act_two_initiator(h, fd, &re); - act_three_initiator(h, fd, &re, my_id); - - /* We need this for re-keying */ - *ck = h->ck; - - /* BOLT #8: - * - * * `sk, rk = HKDF(ck, zero)` - * - * * where `zero` is a zero-length plaintext, `sk` is the key to - * be used by the initiator to encrypt messages to the - * responder, and `rk` is the key to be used by the initiator - * to decrypt messages sent by the responder. - * - * * This step generates the final encryption keys to be used for - * sending and receiving messages for the duration of the - * session. - */ - hkdf_two_keys(sk, rk, ck, NULL, 0); - status_trace("output: sk,rk=0x%s,0x%s", - tal_hexstr(trc, sk, sizeof(*sk)), - tal_hexstr(trc, rk, sizeof(*rk))); - tal_free(tmpctx); -} - -static void responder(int fd, - const struct pubkey *my_id, - struct pubkey *their_id, - struct secret *ck, struct secret *sk, struct secret *rk) -{ - const tal_t *tmpctx = tal_tmpctx(NULL); - struct handshake *h = new_handshake(tmpctx, my_id); - struct pubkey re; - - act_one_responder(h, fd, &re); - act_two_responder(h, fd, &re); - act_three_responder(h, fd, their_id); - - /* We need this for re-keying */ - *ck = h->ck; - - /* BOLT #8: - * - * * `rk, sk = HKDF(ck, zero)` - * * where `zero` is a zero-length plaintext, `rk` is the key to - * be used by the responder to decrypt the messages sent by the - * initiator, and `sk` is the key to be used by the responder - * to encrypt messages to the initiator, - * - * * This step generates the final encryption keys to be used for - * sending and receiving messages for the duration of the - * session. - */ - hkdf_two_keys(rk, sk, ck, NULL, 0); - status_trace("output: rk,sk=0x%s,0x%s", - tal_hexstr(trc, rk, sizeof(*rk)), - tal_hexstr(trc, sk, sizeof(*sk))); - tal_free(tmpctx); -} - -#ifndef TESTING -static void exchange_init(int fd, struct crypto_state *cs, - u8 **gfeatures, u8 **lfeatures) -{ - /* BOLT #1: - * - * The sending node SHOULD use the minimum lengths required to - * represent the feature fields. - * - * The sender MUST set feature bits as defined in [BOLT - * #9](09-features.md), and MUST set to zero any feature bits that are - * not defined. - */ - u8 *localfeatures = tal_arrz(NULL, u8, 1); - localfeatures[0] = LOCALFEATURES_INITIAL_ROUTING_SYNC; - u8 *msg = towire_init(NULL, NULL, localfeatures); - localfeatures = tal_free(localfeatures); - - if (!sync_crypto_write(cs, fd, msg)) - status_failed(STATUS_FAIL_PEER_IO, - "PEER_WRITE_FAILED: %s", strerror(errno)); - - /* BOLT #1: - * - * Each node MUST wait to receive `init` before sending any other - * messages. - */ - msg = sync_crypto_read(NULL, cs, fd); - if (!msg) - status_failed(STATUS_FAIL_PEER_IO, - "INITMSG_READ_FAILED: %s", strerror(errno)); - - if (!fromwire_init(msg, msg, NULL, gfeatures, lfeatures)) - status_failed(STATUS_FAIL_PEER_BAD, "bad init: %s", - tal_hex(msg, msg)); -} - -/* We expect hsmfd as fd 3, clientfd as 4 */ -int main(int argc, char *argv[]) -{ - u8 *msg; - struct pubkey my_id, their_id; - int hsmfd = 3, clientfd = 4; - struct secret ck, rk, sk; - struct crypto_state cs; - u8 *gfeatures, *lfeatures; - - if (argc == 2 && streq(argv[1], "--version")) { - printf("%s\n", version()); - exit(0); - } - - subdaemon_debug(argc, argv); - secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY - | SECP256K1_CONTEXT_SIGN); - status_setup_sync(REQ_FD); - - hsm_setup(hsmfd); - - msg = wire_sync_read(NULL, REQ_FD); - - if (fromwire_handshake_responder(msg, NULL, &my_id)) { - responder(clientfd, &my_id, &their_id, &ck, &sk, &rk); - - cs.rn = cs.sn = 0; - cs.sk = sk; - cs.rk = rk; - cs.r_ck = cs.s_ck = ck; - exchange_init(clientfd, &cs, &gfeatures, &lfeatures); - wire_sync_write(REQ_FD, - towire_handshake_responder_reply(msg, - &their_id, - &cs, - gfeatures, - lfeatures)); - } else if (fromwire_handshake_initiator(msg, NULL, &my_id, - &their_id)) { - initiator(clientfd, &my_id, &their_id, &ck, &sk, &rk); - cs.rn = cs.sn = 0; - cs.sk = sk; - cs.rk = rk; - cs.r_ck = cs.s_ck = ck; - exchange_init(clientfd, &cs, &gfeatures, &lfeatures); - wire_sync_write(REQ_FD, - towire_handshake_initiator_reply(msg, &cs, - gfeatures, - lfeatures)); - } else - master_badmsg(WIRE_HANDSHAKE_INITIATOR, msg); - - /* Hand back the fd. */ - fdpass_send(REQ_FD, clientfd); - - tal_free(msg); - return 0; -} -#endif /* TESTING */ diff --git a/handshaked/handshake_wire.csv b/handshaked/handshake_wire.csv deleted file mode 100644 index f81480971..000000000 --- a/handshaked/handshake_wire.csv +++ /dev/null @@ -1,31 +0,0 @@ -#include - -# FIXME: This is probably too finegrained. -initr_act_one,14001 -initr_act_two,14002 -initr_act_three,14003 -respr_act_one,14011 -respr_act_two,14012 -respr_act_three,14013 -success,4000 - -handshake_responder,4001 -handshake_responder,,my_id,struct pubkey -handshake_responder_reply,4101 -handshake_responder_reply,,initiator_id,struct pubkey -handshake_responder_reply,,cs,struct crypto_state -handshake_responder_reply,,gflen,u16 -handshake_responder_reply,,globalfeatures,gflen*u8 -handshake_responder_reply,,lflen,u16 -handshake_responder_reply,,localfeatures,lflen*u8 - -handshake_initiator,4002 -handshake_initiator,,my_id,struct pubkey -handshake_initiator,,responder_id,struct pubkey - -handshake_initiator_reply,4102 -handshake_initiator_reply,,cs,struct crypto_state -handshake_initiator_reply,,gflen,u16 -handshake_initiator_reply,,globalfeatures,gflen*u8 -handshake_initiator_reply,,lflen,u16 -handshake_initiator_reply,,localfeatures,lflen*u8 diff --git a/handshaked/test/.gitignore b/handshaked/test/.gitignore deleted file mode 100644 index 620f7c82e..000000000 --- a/handshaked/test/.gitignore +++ /dev/null @@ -1 +0,0 @@ -run-handshake diff --git a/handshaked/test/Makefile b/handshaked/test/Makefile deleted file mode 100644 index 5a6992284..000000000 --- a/handshaked/test/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -check: lightningd/handshake-tests - -# Note that these actually #include everything they need, except ccan/ and bitcoin/. -# That allows for unit testing of statics, and special effects. -LIGHTNINGD_HANDSHAKE_TEST_SRC := $(wildcard lightningd/handshake/test/run-*.c) -LIGHTNINGD_HANDSHAKE_TEST_OBJS := $(LIGHTNINGD_HANDSHAKE_TEST_SRC:.c=.o) -LIGHTNINGD_HANDSHAKE_TEST_PROGRAMS := $(LIGHTNINGD_HANDSHAKE_TEST_OBJS:.o=) - -LIGHTNINGD_HANDSHAKE_TEST_COMMON_OBJS := \ - common/cryptomsg.o \ - common/daemon_conn.o \ - common/dev_disconnect.o \ - common/htlc_state.o \ - common/msg_queue.o \ - common/pseudorand.o \ - common/status.o \ - common/type_to_string.o \ - common/utils.o - -update-mocks: $(LIGHTNINGD_HANDSHAKE_TEST_SRC:%=update-mocks/%) - -$(LIGHTNINGD_HANDSHAKE_TEST_PROGRAMS): $(LIGHTNINGD_HANDSHAKE_TEST_COMMON_OBJS) $(LIGHTNINGD_HANDSHAKE_GEN_SRC:.c=.o) $(BITCOIN_OBJS) $(WIRE_OBJS) - -$(LIGHTNINGD_HANDSHAKE_TEST_OBJS): $(LIGHTNINGD_HANDSHAKE_HEADERS) - -ALL_OBJS += $(LIGHTNINGD_HANDSHAKE_TEST_OBJS) -ALL_TEST_PROGRAMS += $(LIGHTNINGD_HANDSHAKE_TEST_PROGRAMS) - -lightningd/handshake-tests: $(LIGHTNINGD_HANDSHAKE_TEST_PROGRAMS:%=unittest/%) - diff --git a/handshaked/test/run-handshake.c b/handshaked/test/run-handshake.c deleted file mode 100644 index 23cf665ea..000000000 --- a/handshaked/test/run-handshake.c +++ /dev/null @@ -1,163 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Since we use pipes, we need different fds for read and write. */ -static int read_fd, write_fd; - -static bool fake_read_all(int fd, void *buf, size_t count) -{ - return read_all(read_fd, buf, count); -} - -static ssize_t fake_write_all(int fd, const void *buf, size_t count) -{ - return write_all(write_fd, buf, count); -} - -static const char *status_prefix; - -/* Simply print out status updates. */ -#define status_send_sync(msg) \ - printf("%s:# Act %s\n", status_prefix, \ - fromwire_peektype(msg) == WIRE_INITR_ACT_ONE ? "One" \ - : fromwire_peektype(msg) == WIRE_INITR_ACT_TWO ? "Two" \ - : fromwire_peektype(msg) == WIRE_INITR_ACT_THREE ? "Three" \ - : fromwire_peektype(msg) == WIRE_RESPR_ACT_ONE ? "One" \ - : fromwire_peektype(msg) == WIRE_RESPR_ACT_TWO ? "Two" \ - : fromwire_peektype(msg) == WIRE_RESPR_ACT_THREE ? "Three" \ - : "UNKNOWN") -#define status_failed(code, fmt, ...) \ - errx(1, "%s:%s:" fmt "\n", status_prefix, #code, __VA_ARGS__) -#define status_trace(fmt, ...) \ - printf("%s:" fmt "\n", status_prefix, __VA_ARGS__) - -#define read_all fake_read_all -#define write_all fake_write_all - -/* No randomness please, we want to replicate test vectors. */ -#include - -static unsigned char e_priv[32]; -#define randombytes_buf(secret, len) memcpy((secret), e_priv, len) - -#define TESTING -#include "../handshake.c" -#include -#include - -secp256k1_context *secp256k1_ctx; -const void *trc; -static struct privkey privkey; - -void hsm_setup(int fd) -{ -} - -bool hsm_do_ecdh(struct secret *ss, const struct pubkey *point) -{ - return secp256k1_ecdh(secp256k1_ctx, ss->data, &point->pubkey, - privkey.secret.data) == 1; -} - -int main(void) -{ - int fds1[2], fds2[2]; - struct pubkey responder_id; - struct privkey responder_privkey; - struct secret ck, sk, rk; - const tal_t *ctx = tal_tmpctx(NULL); - - trc = tal_tmpctx(ctx); - - secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY - | SECP256K1_CONTEXT_SIGN); - - memset(responder_privkey.secret.data, 0x21, - sizeof(responder_privkey.secret.data)); - if (!secp256k1_ec_pubkey_create(secp256k1_ctx, - &responder_id.pubkey, - responder_privkey.secret.data)) - errx(1, "Keygen failed"); - - if (pipe(fds1) != 0 || pipe(fds2) != 0) - err(1, "Making pipes"); - - switch (fork()) { - case -1: - err(1, "fork failed"); - case 0: { - struct pubkey their_id; - - memset(e_priv, 0x22, sizeof(e_priv)); - read_fd = fds1[0]; - write_fd = fds2[1]; - close(fds1[1]); - close(fds2[0]); - privkey = responder_privkey; - status_prefix = "RESPR"; - status_trace("ls.priv: 0x%s", - tal_hexstr(trc, &responder_privkey, - sizeof(responder_privkey))); - status_trace("ls.pub: 0x%s", - type_to_string(trc, struct pubkey, &responder_id)); - responder(-1, &responder_id, &their_id, &ck, &sk, &rk); - if (!write_all(write_fd, &ck, sizeof(ck)) - || !write_all(write_fd, &sk, sizeof(sk)) - || !write_all(write_fd, &rk, sizeof(rk))) - err(1, "writing out secrets failed"); - goto out; - } - default: { - struct pubkey initiator_id; - struct privkey initiator_privkey; - struct secret their_ck, their_sk, their_rk; - - read_fd = fds2[0]; - write_fd = fds1[1]; - close(fds2[1]); - close(fds1[0]); - - memset(initiator_privkey.secret.data, 0x11, - sizeof(initiator_privkey.secret.data)); - memset(e_priv, 0x12, sizeof(e_priv)); - if (!secp256k1_ec_pubkey_create(secp256k1_ctx, - &initiator_id.pubkey, - initiator_privkey.secret.data)) - errx(1, "Initiator keygen failed"); - privkey = initiator_privkey; - status_prefix = "INITR"; - status_trace("rs.pub: 0x%s", - type_to_string(trc, struct pubkey, &responder_id)); - status_trace("ls.priv: 0x%s", - tal_hexstr(trc, &initiator_privkey, - sizeof(initiator_privkey))); - status_trace("ls.pub: 0x%s", - type_to_string(trc, struct pubkey, &initiator_id)); - - initiator(-1, &initiator_id, &responder_id, &ck, &sk, &rk); - if (!read_all(read_fd, &their_ck, sizeof(their_ck)) - || !read_all(read_fd, &their_sk, sizeof(their_sk)) - || !read_all(read_fd, &their_rk, sizeof(their_rk))) - err(1, "reading their secrets failed"); - - assert(structeq(&ck, &their_ck)); - assert(structeq(&sk, &their_rk)); - assert(structeq(&rk, &their_sk)); - goto out; - } - } - -out: - /* No memory leaks please */ - secp256k1_context_destroy(secp256k1_ctx); - tal_free(ctx); - return 0; -} diff --git a/lightningd/.gitignore b/lightningd/.gitignore index 700129d63..e7deac2b7 100644 --- a/lightningd/.gitignore +++ b/lightningd/.gitignore @@ -2,7 +2,6 @@ lightningd lightning_channeld lightning_connectd lightning_gossipd -lightning_handshaked lightning_hsmd lightning_openingd lightning_closingd diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index 39544b87a..caf90ce2b 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -94,7 +94,6 @@ static const char *daemons[] = { "lightning_channeld", "lightning_closingd", "lightning_gossipd", - "lightning_handshaked", "lightning_hsmd", "lightning_onchaind", "lightning_openingd"