#include #include #include #include #include #include #include #include #include #include #include #include /* FIXME: Pad with dummy nodes, but make sure to check them on recv! */ struct onionmsg_path **make_blindedpath(const tal_t *ctx, const struct pubkey *route, struct pubkey *initial_blinding, struct pubkey *final_blinding) { struct privkey e; struct pubkey *pk_e, *b; struct secret *rho; struct onionmsg_path **path; size_t num = tal_count(route); if (!num) abort(); /* E(i) */ pk_e = tal_arr(tmpctx, struct pubkey, num); /* B(i) */ b = tal_arr(tmpctx, struct pubkey, num); /* rho(i) */ rho = tal_arr(tmpctx, struct secret, num); randombytes_buf(&e, sizeof(e)); if (!pubkey_from_privkey(&e, &pk_e[0])) abort(); for (size_t i = 0; i < num; i++) { struct secret ss; struct secret hmac; struct sha256 h; if (secp256k1_ecdh(secp256k1_ctx, ss.data, &route[i].pubkey, e.secret.data, NULL, NULL) != 1) abort(); subkey_from_hmac("blinded_node_id", &ss, &hmac); b[i] = route[i]; if (i != 0) { if (secp256k1_ec_pubkey_tweak_mul(secp256k1_ctx, &b[i].pubkey, hmac.data) != 1) abort(); } subkey_from_hmac("rho", &ss, &rho[i]); blinding_hash_e_and_ss(&pk_e[i], &ss, &h); if (i != num-1) blinding_next_pubkey(&pk_e[i], &h, &pk_e[i+1]); blinding_next_privkey(&e, &h, &e); } *initial_blinding = pk_e[0]; *final_blinding = pk_e[num-1]; path = tal_arr(ctx, struct onionmsg_path *, num); for (size_t i = 0; i < num; i++) { path[i] = tal(path, struct onionmsg_path); path[i]->node_id = b[i]; } for (size_t i = 0; i < num - 1; i++) { const unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; struct tlv_encmsg_tlvs *inner; int ret; /* Inner is encrypted */ inner = tlv_encmsg_tlvs_new(tmpctx); /* FIXME: We could support scids, too */ inner->next_node_id = cast_const(struct pubkey *, &route[i+1]); path[i]->enctlv = tal_arr(path, u8, 0); towire_encmsg_tlvs(&path[i]->enctlv, inner); towire_pad(&path[i]->enctlv, crypto_aead_chacha20poly1305_ietf_ABYTES); ret = crypto_aead_chacha20poly1305_ietf_encrypt(path[i]->enctlv, NULL, path[i]->enctlv, tal_bytelen(path[i]->enctlv) - crypto_aead_chacha20poly1305_ietf_ABYTES, NULL, 0, NULL, npub, rho[i].data); assert(ret == 0); } /* Final one has no enctlv */ path[num-1]->enctlv = NULL; return path; }