diff --git a/channeld/channeld.c b/channeld/channeld.c index 5e5eeb4a8..7849a24a8 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -2321,6 +2321,7 @@ static void peer_in(struct peer *peer, const u8 *msg) case WIRE_WARNING: case WIRE_ERROR: case WIRE_OBS2_ONION_MESSAGE: + case WIRE_ONION_MESSAGE: abort(); } diff --git a/common/blindedpath.c b/common/blindedpath.c index 9e8569811..7994813b7 100644 --- a/common/blindedpath.c +++ b/common/blindedpath.c @@ -58,12 +58,12 @@ static bool blind_node(const struct privkey *blinding, return true; } -static u8 *enctlv_from_encmsg(const tal_t *ctx, - const struct privkey *blinding, - const struct pubkey *node, - const struct tlv_obs2_encmsg_tlvs *encmsg, - struct privkey *next_blinding, - struct pubkey *node_alias) +static u8 *enctlv_from_encmsg_raw(const tal_t *ctx, + const struct privkey *blinding, + const struct pubkey *node, + const u8 *raw_encmsg TAKES, + struct privkey *next_blinding, + struct pubkey *node_alias) { /* https://github.com/lightningnetwork/lightning-rfc/blob/route-blinding/proposals/route-blinding.md */ struct secret ss, rho; @@ -87,9 +87,7 @@ static u8 *enctlv_from_encmsg(const tal_t *ctx, if (!blind_node(blinding, &ss, node, node_alias, next_blinding)) return NULL; - /* Marshall */ - ret = tal_arr(ctx, u8, 0); - towire_obs2_encmsg_tlvs(&ret, encmsg); + ret = tal_dup_talarr(ctx, u8, raw_encmsg); SUPERVERBOSE("\t\"encmsg_hex\": \"%s\",\n", tal_hex(tmpctx, ret)); /* @@ -115,6 +113,32 @@ static u8 *enctlv_from_encmsg(const tal_t *ctx, return ret; } +static u8 *enctlv_from_obs2_encmsg(const tal_t *ctx, + const struct privkey *blinding, + const struct pubkey *node, + const struct tlv_obs2_encmsg_tlvs *encmsg, + struct privkey *next_blinding, + struct pubkey *node_alias) +{ + u8 *encmsg_raw = tal_arr(NULL, u8, 0); + towire_obs2_encmsg_tlvs(&encmsg_raw, encmsg); + return enctlv_from_encmsg_raw(ctx, blinding, node, take(encmsg_raw), + next_blinding, node_alias); +} + +static u8 *enctlv_from_encmsg(const tal_t *ctx, + const struct privkey *blinding, + const struct pubkey *node, + const struct tlv_encrypted_data_tlv *encmsg, + struct privkey *next_blinding, + struct pubkey *node_alias) +{ + u8 *encmsg_raw = tal_arr(NULL, u8, 0); + towire_encrypted_data_tlv(&encmsg_raw, encmsg); + return enctlv_from_encmsg_raw(ctx, blinding, node, take(encmsg_raw), + next_blinding, node_alias); +} + bool unblind_onion(const struct pubkey *blinding, void (*ecdh)(const struct pubkey *point, struct secret *ss), struct pubkey *onion_key, @@ -136,16 +160,13 @@ bool unblind_onion(const struct pubkey *blinding, hmac.data) == 1; } -static struct tlv_obs2_encmsg_tlvs *decrypt_encmsg(const tal_t *ctx, - const struct pubkey *blinding, - const struct secret *ss, - const u8 *enctlv) +static u8 *decrypt_encmsg_raw(const tal_t *ctx, + const struct pubkey *blinding, + const struct secret *ss, + const u8 *enctlv) { struct secret rho; u8 *dec; - const u8 *cursor; - size_t maxlen; - struct tlv_obs2_encmsg_tlvs *encmsg; /* All-zero npub */ static const unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES]; @@ -161,7 +182,7 @@ static struct tlv_obs2_encmsg_tlvs *decrypt_encmsg(const tal_t *ctx, if (tal_bytelen(enctlv) < crypto_aead_chacha20poly1305_ietf_ABYTES) return NULL; - dec = tal_arr(tmpctx, u8, tal_bytelen(enctlv) + dec = tal_arr(ctx, u8, tal_bytelen(enctlv) - crypto_aead_chacha20poly1305_ietf_ABYTES); if (crypto_aead_chacha20poly1305_ietf_decrypt(dec, NULL, NULL, @@ -169,10 +190,19 @@ static struct tlv_obs2_encmsg_tlvs *decrypt_encmsg(const tal_t *ctx, NULL, 0, npub, rho.data) != 0) - return NULL; + return tal_free(dec); - cursor = dec; - maxlen = tal_bytelen(dec); + return dec; +} + +static struct tlv_obs2_encmsg_tlvs *decrypt_obs2_encmsg(const tal_t *ctx, + const struct pubkey *blinding, + const struct secret *ss, + const u8 *enctlv) +{ + struct tlv_obs2_encmsg_tlvs *encmsg; + const u8 *cursor = decrypt_encmsg_raw(tmpctx, blinding, ss, enctlv); + size_t maxlen = tal_bytelen(cursor); /* BOLT-onion-message #4: * @@ -187,6 +217,156 @@ static struct tlv_obs2_encmsg_tlvs *decrypt_encmsg(const tal_t *ctx, return encmsg; } +static struct tlv_encrypted_data_tlv *decrypt_encmsg(const tal_t *ctx, + const struct pubkey *blinding, + const struct secret *ss, + const u8 *enctlv) +{ + struct tlv_encrypted_data_tlv *encmsg; + const u8 *cursor = decrypt_encmsg_raw(tmpctx, blinding, ss, enctlv); + size_t maxlen = tal_bytelen(cursor); + + /* BOLT-onion-message #4: + * + * - if the `enctlv` is not a valid TLV... + * - MUST drop the message. + */ + encmsg = tlv_encrypted_data_tlv_new(ctx); + if (!fromwire_encrypted_data_tlv(&cursor, &maxlen, encmsg) + || !tlv_fields_valid(encmsg->fields, NULL, NULL)) + return tal_free(encmsg); + + return encmsg; +} + +bool decrypt_enctlv(const struct pubkey *blinding, + const struct secret *ss, + const u8 *enctlv, + struct pubkey *next_node, + struct pubkey *next_blinding) +{ + struct tlv_encrypted_data_tlv *encmsg; + + encmsg = decrypt_encmsg(tmpctx, blinding, ss, enctlv); + if (!encmsg) + return false; + + /* BOLT-onion-message #4: + * + * The reader: + * - if it is not the final node according to the onion encryption: + *... + * - if the `enctlv` ... does not contain + * `next_node_id`: + * - MUST drop the message. + */ + if (!encmsg->next_node_id) + return false; + + /* BOLT-onion-message #4: + * The reader: + * - if it is not the final node according to the onion encryption: + *... + * - if the `enctlv` contains `path_id`: + * - MUST drop the message. + */ + if (encmsg->path_id) + return false; + + /* BOLT-onion-message #4: + * The reader: + * - if it is not the final node according to the onion encryption: + *... + * - if `blinding` is specified in the `enctlv`: + * - MUST pass that as `blinding` in the `onion_message` + * - otherwise: + * - MUST pass `blinding` derived as in + * [Route Blinding][route-blinding] (i.e. + * `E(i+1) = H(E(i) || ss(i)) * E(i)`). + */ + *next_node = *encmsg->next_node_id; + if (encmsg->next_blinding_override) + *next_blinding = *encmsg->next_blinding_override; + else { + /* E(i-1) = H(E(i) || ss(i)) * E(i) */ + struct sha256 h; + blinding_hash_e_and_ss(blinding, ss, &h); + blinding_next_pubkey(blinding, &h, next_blinding); + } + return true; +} + +bool decrypt_final_enctlv(const tal_t *ctx, + const struct pubkey *blinding, + const struct secret *ss, + const u8 *enctlv, + const struct pubkey *my_id, + struct pubkey *alias, + struct secret **path_id) +{ + struct tlv_encrypted_data_tlv *encmsg; + struct secret node_id_blinding; + + /* Repeat the tweak to get the alias it was using for us */ + subkey_from_hmac("blinded_node_id", ss, &node_id_blinding); + *alias = *my_id; + if (secp256k1_ec_pubkey_tweak_mul(secp256k1_ctx, + &alias->pubkey, + node_id_blinding.data) != 1) + return false; + + encmsg = decrypt_encmsg(tmpctx, blinding, ss, enctlv); + if (!encmsg) + return false; + + if (tal_bytelen(encmsg->path_id) == sizeof(**path_id)) { + *path_id = tal(ctx, struct secret); + memcpy(*path_id, encmsg->path_id, sizeof(**path_id)); + } else + *path_id = NULL; + + return true; +} + +u8 *create_enctlv(const tal_t *ctx, + const struct privkey *blinding, + const struct pubkey *node, + const struct pubkey *next_node, + size_t padlen, + const struct pubkey *next_blinding_override, + struct privkey *next_blinding, + struct pubkey *node_alias) +{ + struct tlv_encrypted_data_tlv *encmsg = tlv_encrypted_data_tlv_new(tmpctx); + if (padlen) + encmsg->padding = tal_arrz(encmsg, u8, padlen); + encmsg->next_node_id = cast_const(struct pubkey *, next_node); + encmsg->next_blinding_override = cast_const(struct pubkey *, next_blinding_override); + + return enctlv_from_encmsg(ctx, blinding, node, encmsg, + next_blinding, node_alias); +} + +u8 *create_final_enctlv(const tal_t *ctx, + const struct privkey *blinding, + const struct pubkey *final_node, + size_t padlen, + const struct secret *path_id, + struct pubkey *node_alias) +{ + struct tlv_encrypted_data_tlv *encmsg = tlv_encrypted_data_tlv_new(tmpctx); + struct privkey unused_next_blinding; + + if (padlen) + encmsg->padding = tal_arrz(encmsg, u8, padlen); + if (path_id) + encmsg->path_id = (u8 *)tal_dup(encmsg, struct secret, path_id); + + return enctlv_from_encmsg(ctx, blinding, final_node, encmsg, + &unused_next_blinding, node_alias); +} + +/* Obsolete variants */ bool decrypt_obs2_enctlv(const struct pubkey *blinding, const struct secret *ss, const u8 *enctlv, @@ -195,7 +375,7 @@ bool decrypt_obs2_enctlv(const struct pubkey *blinding, { struct tlv_obs2_encmsg_tlvs *encmsg; - encmsg = decrypt_encmsg(tmpctx, blinding, ss, enctlv); + encmsg = decrypt_obs2_encmsg(tmpctx, blinding, ss, enctlv); if (!encmsg) return false; @@ -263,7 +443,7 @@ bool decrypt_obs2_final_enctlv(const tal_t *ctx, node_id_blinding.data) != 1) return false; - encmsg = decrypt_encmsg(tmpctx, blinding, ss, enctlv); + encmsg = decrypt_obs2_encmsg(tmpctx, blinding, ss, enctlv); if (!encmsg) return false; @@ -291,8 +471,8 @@ u8 *create_obs2_enctlv(const tal_t *ctx, encmsg->next_node_id = cast_const(struct pubkey *, next_node); encmsg->next_blinding = cast_const(struct pubkey *, override_blinding); - return enctlv_from_encmsg(ctx, blinding, node, encmsg, - next_blinding, node_alias); + return enctlv_from_obs2_encmsg(ctx, blinding, node, encmsg, + next_blinding, node_alias); } u8 *create_obs2_final_enctlv(const tal_t *ctx, @@ -310,6 +490,6 @@ u8 *create_obs2_final_enctlv(const tal_t *ctx, if (self_id) encmsg->self_id = (u8 *)tal_dup(encmsg, struct secret, self_id); - return enctlv_from_encmsg(ctx, blinding, final_node, encmsg, - &unused_next_blinding, node_alias); + return enctlv_from_obs2_encmsg(ctx, blinding, final_node, encmsg, + &unused_next_blinding, node_alias); } diff --git a/common/blindedpath.h b/common/blindedpath.h index a207c316d..f34159395 100644 --- a/common/blindedpath.h +++ b/common/blindedpath.h @@ -17,18 +17,18 @@ struct secret; * @node: the pubkey of the node to encrypt for * @next_node: the pubkey of the next node, to place in enctlv * @padlen: if non-zero, the bytes of padding to add (also adds 2 byte padding hdr) - * @override_blinding: the optional blinding point to place in enctlv + * @next_blinding_override: the optional blinding point to place in enctlv * @next_blinding: (out) e(i+1), the next blinding secret. * @node_alias: (out) the blinded pubkey of the node to tell the recipient. * * Returns the enctlv blob, or NULL if the secret is invalid. */ -u8 *create_obs2_enctlv(const tal_t *ctx, +u8 *create_enctlv(const tal_t *ctx, const struct privkey *blinding, const struct pubkey *node, const struct pubkey *next_node, size_t padlen, - const struct pubkey *override_blinding, + const struct pubkey *next_blinding_override, struct privkey *next_blinding, struct pubkey *node_alias) NON_NULL_ARGS(2, 3, 4, 7, 8); @@ -39,16 +39,16 @@ u8 *create_obs2_enctlv(const tal_t *ctx, * @blinding: e(i), the blinding secret * @final_node: the pubkey of the node to encrypt for * @padlen: if non-zero, the bytes of padding to add (also adds 2 byte padding hdr) - * @self_id: secret to include in enctlv, if not NULL. + * @path_id: secret to include in enctlv, if not NULL. * @node_alias: (out) the blinded pubkey of the node to tell the recipient. * * If it fails, it means one of the privkeys is bad. */ -u8 *create_obs2_final_enctlv(const tal_t *ctx, +u8 *create_final_enctlv(const tal_t *ctx, const struct privkey *blinding, const struct pubkey *final_node, size_t padlen, - const struct secret *self_id, + const struct secret *path_id, struct pubkey *node_alias) NON_NULL_ARGS(2, 3, 6); @@ -77,7 +77,7 @@ bool unblind_onion(const struct pubkey *blinding, * * Returns false if decryption failed or encmsg was malformed. */ -bool decrypt_obs2_enctlv(const struct pubkey *blinding, +bool decrypt_enctlv(const struct pubkey *blinding, const struct secret *ss, const u8 *enctlv, struct pubkey *next_node, @@ -86,23 +86,55 @@ bool decrypt_obs2_enctlv(const struct pubkey *blinding, /** * decrypt_final_enctlv - Decrypt an encmsg to form an enctlv. - * @ctx: tal context for @self_id + * @ctx: tal context for @path_id * @blinding: E(i), the blinding pubkey the previous peer gave us. * @ss: the blinding secret from unblind_onion(). * @enctlv: the enctlv from the onion (tal, may be NULL). * @my_id: the pubkey of this node. * @alias: (out) the node_id this was addressed to. - * @self_id: (out) the secret contained in the enctlv, if any. + * @path_id: (out) the secret contained in the enctlv, if any (NULL if invalid or unset) * * Returns false if decryption failed or encmsg was malformed. */ -bool decrypt_obs2_final_enctlv(const tal_t *ctx, +bool decrypt_final_enctlv(const tal_t *ctx, const struct pubkey *blinding, const struct secret *ss, const u8 *enctlv, const struct pubkey *my_id, struct pubkey *alias, - struct secret **self_id) + struct secret **path_id) + NON_NULL_ARGS(1, 2, 4, 5); + +/* Obsolete variants */ +u8 *create_obs2_enctlv(const tal_t *ctx, + const struct privkey *blinding, + const struct pubkey *node, + const struct pubkey *next_node, + size_t padlen, + const struct pubkey *override_blinding, + struct privkey *next_blinding, + struct pubkey *node_alias) + NON_NULL_ARGS(2, 3, 4, 7, 8); +u8 *create_obs2_final_enctlv(const tal_t *ctx, + const struct privkey *blinding, + const struct pubkey *final_node, + size_t padlen, + const struct secret *self_id, + struct pubkey *node_alias) + NON_NULL_ARGS(2, 3, 6); +bool decrypt_obs2_enctlv(const struct pubkey *blinding, + const struct secret *ss, + const u8 *enctlv, + struct pubkey *next_node, + struct pubkey *next_blinding) + NON_NULL_ARGS(1, 2, 4, 5); +bool decrypt_obs2_final_enctlv(const tal_t *ctx, + const struct pubkey *blinding, + const struct secret *ss, + const u8 *enctlv, + const struct pubkey *my_id, + struct pubkey *alias, + struct secret **self_id) NON_NULL_ARGS(1, 2, 4, 5); #endif /* LIGHTNING_COMMON_BLINDEDPATH_H */ diff --git a/common/json_helpers.c b/common/json_helpers.c index 0fa2233c9..ee7f23531 100644 --- a/common/json_helpers.c +++ b/common/json_helpers.c @@ -164,12 +164,48 @@ json_to_obs2_reply_path(const tal_t *ctx, const char *buffer, const jsmntok_t *t rpath->path = tal_arr(rpath, struct onionmsg_path *, hops->size); json_for_each_arr(i, t, hops) { rpath->path[i] = tal(rpath->path, struct onionmsg_path); - err = json_scan(tmpctx, buffer, t, "{id:%,enctlv:%}", + err = json_scan(tmpctx, buffer, t, "{id:%,encrypted_recipient_data:%}", JSON_SCAN(json_to_pubkey, &rpath->path[i]->node_id), JSON_SCAN_TAL(rpath->path[i], json_tok_bin_from_hex, - &rpath->path[i]->enctlv)); + &rpath->path[i]->encrypted_recipient_data)); + if (err) + return tal_free(rpath); + } + + return rpath; +} + +struct tlv_onionmsg_payload_reply_path * +json_to_reply_path(const tal_t *ctx, const char *buffer, const jsmntok_t *tok) +{ + struct tlv_onionmsg_payload_reply_path *rpath; + const jsmntok_t *hops, *t; + size_t i; + const char *err; + + rpath = tal(ctx, struct tlv_onionmsg_payload_reply_path); + err = json_scan(tmpctx, buffer, tok, "{blinding:%,first_node_id:%}", + JSON_SCAN(json_to_pubkey, &rpath->blinding), + JSON_SCAN(json_to_pubkey, &rpath->first_node_id), + NULL); + if (err) + return tal_free(rpath); + + hops = json_get_member(buffer, tok, "hops"); + if (!hops || hops->size < 1) + return tal_free(rpath); + + rpath->path = tal_arr(rpath, struct onionmsg_path *, hops->size); + json_for_each_arr(i, t, hops) { + rpath->path[i] = tal(rpath->path, struct onionmsg_path); + err = json_scan(tmpctx, buffer, t, "{id:%,encrypted_recipient_data:%}", + JSON_SCAN(json_to_pubkey, + &rpath->path[i]->node_id), + JSON_SCAN_TAL(rpath->path[i], + json_tok_bin_from_hex, + &rpath->path[i]->encrypted_recipient_data)); if (err) return tal_free(rpath); } diff --git a/common/json_helpers.h b/common/json_helpers.h index c6febd343..3e1064240 100644 --- a/common/json_helpers.h +++ b/common/json_helpers.h @@ -80,6 +80,10 @@ bool split_tok(const char *buffer, const jsmntok_t *tok, jsmntok_t *b); /* Extract reply path from this JSON */ +struct tlv_onionmsg_payload_reply_path * +json_to_reply_path(const tal_t *ctx, const char *buffer, const jsmntok_t *tok); + +/* Obsolete version! */ struct tlv_obs2_onionmsg_payload_reply_path * json_to_obs2_reply_path(const tal_t *ctx, const char *buffer, const jsmntok_t *tok); diff --git a/common/onion.c b/common/onion.c index 4743117da..aeab17de1 100644 --- a/common/onion.c +++ b/common/onion.c @@ -82,8 +82,8 @@ u8 *onion_nonfinal_hop(const tal_t *ctx, tlv->short_channel_id = cast_const(struct short_channel_id *, scid); #if EXPERIMENTAL_FEATURES - tlv->blinding_seed = cast_const(struct pubkey *, blinding); - tlv->enctlv = cast_const(u8 *, enctlv); + tlv->blinding_point = cast_const(struct pubkey *, blinding); + tlv->encrypted_recipient_data = cast_const(u8 *, enctlv); #endif return make_tlv_hop(ctx, tlv); } else { @@ -135,8 +135,8 @@ u8 *onion_final_hop(const tal_t *ctx, tlv->payment_data = &tlv_pdata; } #if EXPERIMENTAL_FEATURES - tlv->blinding_seed = cast_const(struct pubkey *, blinding); - tlv->enctlv = cast_const(u8 *, enctlv); + tlv->blinding_point = cast_const(struct pubkey *, blinding); + tlv->encrypted_recipient_data = cast_const(u8 *, enctlv); #endif return make_tlv_hop(ctx, tlv); } else { @@ -362,10 +362,10 @@ struct onion_payload *onion_decode(const tal_t *ctx, #if EXPERIMENTAL_FEATURES if (!p->blinding) { /* If we have no blinding, it could be in TLV. */ - if (tlv->blinding_seed) { + if (tlv->blinding_point) { p->blinding = tal_dup(p, struct pubkey, - tlv->blinding_seed); + tlv->blinding_point); ecdh(p->blinding, &p->blinding_ss); } } else @@ -377,12 +377,12 @@ struct onion_payload *onion_decode(const tal_t *ctx, if (rs->nextcase == ONION_FORWARD) { struct tlv_tlv_payload *ntlv; - if (!tlv->enctlv) + if (!tlv->encrypted_recipient_data) goto fail; ntlv = decrypt_tlv(tmpctx, &p->blinding_ss, - tlv->enctlv); + tlv->encrypted_recipient_data); if (!ntlv) goto fail; diff --git a/common/test/run-blindedpath_enctlv.c b/common/test/run-blindedpath_enctlv.c index 867b8c82f..477220765 100644 --- a/common/test/run-blindedpath_enctlv.c +++ b/common/test/run-blindedpath_enctlv.c @@ -136,7 +136,7 @@ int main(int argc, char *argv[]) /* We output the JSON test vectors. */ printf("[{"); - json_strfield("test name", "Simple enctlv for Alice, next is Bob"); + json_strfield("test name", "Simple encrypted_recipient_data for Alice, next is Bob"); json_strfield("node_privkey", type_to_string(tmpctx, struct privkey, &alice)); json_strfield("node_id", @@ -145,14 +145,14 @@ int main(int argc, char *argv[]) type_to_string(tmpctx, struct privkey, &blinding)); json_strfield("blinding", type_to_string(tmpctx, struct pubkey, &blinding_pub)); - printf("\t\"encmsg\": {\n" + printf("\t\"encrypted_data_tlv\": {\n" "\t\t\"next_node_id\": \"%s\"\n" "\t},\n", type_to_string(tmpctx, struct pubkey, &bob_id)); enctlv = create_obs2_enctlv(tmpctx, &blinding, &alice_id, &bob_id, 0, NULL, &blinding, &alias); - printf("\t\"enctlv_hex\": \"%s\"\n" + printf("\t\"encrypted_recipient_data_hex\": \"%s\"\n" "},\n", tal_hex(tmpctx, enctlv)); @@ -164,7 +164,7 @@ int main(int argc, char *argv[]) printf("{"); json_strfield("test name", - "Blinding-key-override enctlv for Bob, next is Carol"); + "Blinding-key-override encrypted_recipient_data for Bob, next is Carol"); json_strfield("node_privkey", type_to_string(tmpctx, struct privkey, &bob)); json_strfield("node_id", @@ -173,7 +173,7 @@ int main(int argc, char *argv[]) type_to_string(tmpctx, struct privkey, &blinding)); json_strfield("blinding", type_to_string(tmpctx, struct pubkey, &blinding_pub)); - printf("\t\"encmsg\": {\n" + printf("\t\"encrypted_data_tlv\": {\n" "\t\t\"next_node_id\": \"%s\",\n" "\t\t\"blinding\": \"%s\"\n" "\t},\n", @@ -182,7 +182,7 @@ int main(int argc, char *argv[]) enctlv = create_obs2_enctlv(tmpctx, &blinding, &bob_id, &carol_id, 0, &override_blinding_pub, &blinding, &alias); - printf("\t\"enctlv_hex\": \"%s\"\n" + printf("\t\"encrypted_recipient_data_hex\": \"%s\"\n" "},\n", tal_hex(tmpctx, enctlv)); @@ -193,7 +193,7 @@ int main(int argc, char *argv[]) blinding_pub = override_blinding_pub; printf("{"); - json_strfield("test name", "Padded enctlv for Carol, next is Dave"); + json_strfield("test name", "Padded encrypted_recipient_data for Carol, next is Dave"); json_strfield("node_privkey", type_to_string(tmpctx, struct privkey, &carol)); json_strfield("node_id", @@ -202,7 +202,7 @@ int main(int argc, char *argv[]) type_to_string(tmpctx, struct privkey, &blinding)); json_strfield("blinding", type_to_string(tmpctx, struct pubkey, &blinding_pub)); - printf("\t\"encmsg\": {\n" + printf("\t\"encrypted_data_tlv\": {\n" "\t\t\"next_node_id\": \"%s\",\n" "\t\t\"padding\": \"%s\"\n" "\t},\n", @@ -211,7 +211,7 @@ int main(int argc, char *argv[]) enctlv = create_obs2_enctlv(tmpctx, &blinding, &carol_id, &dave_id, 35, NULL, &blinding, &alias); - printf("\t\"enctlv_hex\": \"%s\"\n" + printf("\t\"encrypted_recipient_data_hex\": \"%s\"\n" "}]\n", tal_hex(tmpctx, enctlv)); diff --git a/devtools/blindedpath.c b/devtools/blindedpath.c index 57d320894..3e46662ab 100644 --- a/devtools/blindedpath.c +++ b/devtools/blindedpath.c @@ -269,11 +269,11 @@ int main(int argc, char **argv) /* Look for enctlv */ if (!outer->enctlv) - errx(1, "No enctlv field"); + errx(1, "No encrypted_recipient_data field"); if (tal_bytelen(outer->enctlv) < crypto_aead_chacha20poly1305_ietf_ABYTES) - errx(1, "enctlv field too short"); + errx(1, "encrypted_recipient_data field too short"); dec = tal_arr(tmpctx, u8, tal_bytelen(outer->enctlv) @@ -286,7 +286,7 @@ int main(int argc, char **argv) npub, rho.data); if (ret != 0) - errx(1, "Failed to decrypt enctlv field"); + errx(1, "Failed to decrypt encrypted_recipient_data field"); printf("Contents: %s\n", tal_hex(tmpctx, dec)); diff --git a/devtools/bolt12-cli.c b/devtools/bolt12-cli.c index aa4dbf2bb..4e63c13be 100644 --- a/devtools/bolt12-cli.c +++ b/devtools/bolt12-cli.c @@ -270,7 +270,7 @@ static bool print_blindedpaths(struct blinded_path **paths, printf(" %s:%s", type_to_string(tmpctx, struct pubkey, &p[j]->node_id), - tal_hex(tmpctx, p[j]->enctlv)); + tal_hex(tmpctx, p[j]->encrypted_recipient_data)); if (blindedpay) { if (bp_idx < tal_count(blindedpay)) printf("fee=%u/%u,cltv=%u,features=%s", diff --git a/doc/PLUGINS.md b/doc/PLUGINS.md index 752b41233..07e045374 100644 --- a/doc/PLUGINS.md +++ b/doc/PLUGINS.md @@ -1542,7 +1542,7 @@ The payload for a call follows this format: "reply_first_node": "02df5ffe895c778e10f7742a6c5b8a0cefbe9465df58b92fadeb883752c8107c8f", "reply_blinding": "02df5ffe895c778e10f7742a6c5b8a0cefbe9465df58b92fadeb883752c8107c8f", "reply_path": [ {"id": "02df5ffe895c778e10f7742a6c5b8a0cefbe9465df58b92fadeb883752c8107c8f", - "enctlv": "0a020d0d", + "encrypted_recipient_data": "0a020d0d", "blinding": "02df5ffe895c778e10f7742a6c5b8a0cefbe9465df58b92fadeb883752c8107c8f"} ], "invoice_request": "0a020d0d", "invoice": "0a020d0d", diff --git a/doc/lightning-decode.7.md b/doc/lightning-decode.7.md index 6708071ed..81d8a62b9 100644 --- a/doc/lightning-decode.7.md +++ b/doc/lightning-decode.7.md @@ -42,7 +42,7 @@ If **type** is "bolt12 offer", and **valid** is *true*: - **blinding** (pubkey): blinding factor for this path - **path** (array of objects): an individual path: - **node_id** (pubkey): node_id of the hop - - **enctlv** (hex): encrypted TLV entry for this hop + - **encrypted_recipient_data** (hex): encrypted TLV entry for this hop - **quantity_min** (u64, optional): the minimum quantity - **quantity_max** (u64, optional): the maximum quantity - **recurrence** (object, optional): how often to this offer should be used: @@ -82,7 +82,7 @@ If **type** is "bolt12 invoice", and **valid** is *true*: - **blinding** (pubkey): blinding factor for this path - **path** (array of objects): an individual path: - **node_id** (pubkey): node_id of the hop - - **enctlv** (hex): encrypted TLV entry for this hop + - **encrypted_recipient_data** (hex): encrypted TLV entry for this hop - **quantity** (u64, optional): the quantity ordered - **recurrence_counter** (u32, optional): the 0-based counter for a recurring payment - **recurrence_start** (u32, optional): the optional start period for a recurring payment @@ -180,4 +180,4 @@ RESOURCES Main web site: -[comment]: # ( SHA256STAMP:cd4a18d07c23b6a995f8db7cac25344e340e512c786b8cf743f56ecceeb84960) +[comment]: # ( SHA256STAMP:d05b5fc1bf230b3bbd03e2023fb0c6bbefb700f7c3cfb43512da48dbce45f005) diff --git a/doc/schemas/decode.schema.json b/doc/schemas/decode.schema.json index 9e12c1588..808ef8f43 100644 --- a/doc/schemas/decode.schema.json +++ b/doc/schemas/decode.schema.json @@ -146,7 +146,7 @@ "type": "object", "required": [ "node_id", - "enctlv" + "encrypted_recipient_data" ], "additionalProperties": false, "properties": { @@ -154,7 +154,7 @@ "type": "pubkey", "description": "node_id of the hop" }, - "enctlv": { + "encrypted_recipient_data": { "type": "hex", "description": "encrypted TLV entry for this hop" } @@ -388,7 +388,7 @@ "type": "object", "required": [ "node_id", - "enctlv" + "encrypted_recipient_data" ], "additionalProperties": false, "properties": { @@ -396,7 +396,7 @@ "type": "pubkey", "description": "node_id of the hop" }, - "enctlv": { + "encrypted_recipient_data": { "type": "hex", "description": "encrypted TLV entry for this hop" } diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index b9e07a353..419ed2ca1 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -520,6 +520,13 @@ static struct io_plan *onionmsg_req(struct io_conn *conn, struct daemon *daemon, return daemon_conn_read_next(conn, daemon->master); } +/* Peer sends an onion msg. */ +static u8 *handle_onion_message(struct peer *peer, const u8 *msg) +{ + /* FIXME! */ + return NULL; +} + /*~ This is where the per-peer daemons send us messages. It's either forwarded * gossip, or a request for information. We deliberately use non-overlapping * message types so we can distinguish them. */ @@ -556,6 +563,9 @@ static struct io_plan *peer_msg_in(struct io_conn *conn, case WIRE_OBS2_ONION_MESSAGE: err = handle_obs2_onion_message(peer, msg); goto handled_relay; + case WIRE_ONION_MESSAGE: + err = handle_onion_message(peer, msg); + goto handled_relay; /* These are non-gossip messages (!is_msg_for_gossipd()) */ case WIRE_WARNING: diff --git a/lightningd/onion_message.c b/lightningd/onion_message.c index 1a0de05e9..9d5ef23ab 100644 --- a/lightningd/onion_message.c +++ b/lightningd/onion_message.c @@ -37,7 +37,8 @@ static void json_add_blindedpath(struct json_stream *stream, for (size_t i = 0; i < tal_count(path); i++) { json_object_start(stream, NULL); json_add_pubkey(stream, "id", &path[i]->node_id); - json_add_hex_talarr(stream, "enctlv", path[i]->enctlv); + json_add_hex_talarr(stream, "encrypted_recipient_data", + path[i]->encrypted_recipient_data); json_object_end(stream); }; json_array_end(stream); @@ -327,7 +328,7 @@ static struct command_result *json_blindedpath(struct command *cmd, for (size_t i = 0; i < nhops - 1; i++) { path[i] = tal(path, struct onionmsg_path); - path[i]->enctlv = create_obs2_enctlv(path[i], + path[i]->encrypted_recipient_data = create_obs2_enctlv(path[i], &blinding_iter, &ids[i], &ids[i+1], @@ -340,7 +341,7 @@ static struct command_result *json_blindedpath(struct command *cmd, /* FIXME: Add padding! */ path[nhops-1] = tal(path, struct onionmsg_path); - path[nhops-1]->enctlv = create_obs2_final_enctlv(path[nhops-1], + path[nhops-1]->encrypted_recipient_data = create_obs2_final_enctlv(path[nhops-1], &blinding_iter, &ids[nhops-1], /* FIXME: Pad? */ diff --git a/lightningd/pay.c b/lightningd/pay.c index 6f4db608f..c6f414f2e 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -1392,7 +1392,7 @@ static struct command_result *param_route_hops(struct command *cmd, p_opt("direction", param_number, &direction), p_opt("style", param_route_hop_style, &style), p_opt("blinding", param_pubkey, &blinding), - p_opt("enctlv", param_bin_from_hex, &enctlv), + p_opt("encrypted_recipient_data", param_bin_from_hex, &enctlv), NULL)) return command_param_failed(); diff --git a/openingd/dualopend.c b/openingd/dualopend.c index 903aaa7f2..795fce83c 100644 --- a/openingd/dualopend.c +++ b/openingd/dualopend.c @@ -1286,6 +1286,7 @@ static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state) case WIRE_ANNOUNCEMENT_SIGNATURES: case WIRE_GOSSIP_TIMESTAMP_FILTER: case WIRE_OBS2_ONION_MESSAGE: + case WIRE_ONION_MESSAGE: case WIRE_ACCEPT_CHANNEL2: case WIRE_TX_ADD_INPUT: case WIRE_TX_REMOVE_INPUT: @@ -1632,6 +1633,7 @@ static bool run_tx_interactive(struct state *state, case WIRE_ANNOUNCEMENT_SIGNATURES: case WIRE_GOSSIP_TIMESTAMP_FILTER: case WIRE_OBS2_ONION_MESSAGE: + case WIRE_ONION_MESSAGE: case WIRE_TX_SIGNATURES: case WIRE_OPEN_CHANNEL2: case WIRE_ACCEPT_CHANNEL2: @@ -3685,6 +3687,7 @@ static u8 *handle_peer_in(struct state *state) case WIRE_ANNOUNCEMENT_SIGNATURES: case WIRE_GOSSIP_TIMESTAMP_FILTER: case WIRE_OBS2_ONION_MESSAGE: + case WIRE_ONION_MESSAGE: case WIRE_ACCEPT_CHANNEL2: case WIRE_TX_ADD_INPUT: case WIRE_TX_REMOVE_INPUT: diff --git a/plugins/offers.c b/plugins/offers.c index 0de0718a9..4a9f98889 100644 --- a/plugins/offers.c +++ b/plugins/offers.c @@ -64,7 +64,7 @@ send_onion_reply(struct command *cmd, json_add_pubkey(req->js, "id", &reply_path->path[i]->node_id); omp = tlv_obs2_onionmsg_payload_new(tmpctx); - omp->enctlv = reply_path->path[i]->enctlv; + omp->enctlv = reply_path->path[i]->encrypted_recipient_data; /* Put payload in last hop. */ if (i == nhops - 1) { @@ -227,7 +227,7 @@ static void json_add_onionmsg_path(struct json_stream *js, { json_object_start(js, fieldname); json_add_pubkey(js, "node_id", &path->node_id); - json_add_hex_talarr(js, "enctlv", path->enctlv); + json_add_hex_talarr(js, "encrypted_recipient_data", path->encrypted_recipient_data); if (payinfo) { json_add_u32(js, "fee_base_msat", payinfo->fee_base_msat); json_add_u32(js, "fee_proportional_millionths", diff --git a/wire/extracted_onion_exp_enctlv.patch b/wire/extracted_onion_exp_enctlv.patch index 59d5b08c6..1897193b8 100644 --- a/wire/extracted_onion_exp_enctlv.patch +++ b/wire/extracted_onion_exp_enctlv.patch @@ -1,13 +1,15 @@ --- wire/extracted_onion_wire_csv 2020-02-25 05:52:39.612291156 +1030 +++ - 2020-03-20 15:11:55.763880895 +1030 -@@ -8,6 +8,10 @@ tlvdata,tlv_payload,short_channel_id,short_channel_id,short_channel_id, +--- wire/onion_exp_wire.csv.~1~ 2021-11-17 10:56:59.947630815 +1030 ++++ wire/onion_exp_wire.csv 2021-11-17 10:59:39.304581244 +1030 +@@ -8,6 +8,10 @@ tlvtype,tlv_payload,payment_data,8 tlvdata,tlv_payload,payment_data,payment_secret,byte,32 tlvdata,tlv_payload,payment_data,total_msat,tu64, -+tlvtype,tlv_payload,enctlv,10 -+tlvdata,tlv_payload,enctlv,enctlv,byte,... -+tlvtype,tlv_payload,blinding_seed,12 -+tlvdata,tlv_payload,blinding_seed,blinding_seed,pubkey, ++tlvtype,tlv_payload,encrypted_recipient_data,10 ++tlvdata,tlv_payload,encrypted_recipient_data,encrypted_data,byte,... ++tlvtype,tlv_payload,blinding_point,12 ++tlvdata,tlv_payload,blinding_point,blinding,point, tlvtype,obs2_onionmsg_payload,reply_path,2 tlvdata,obs2_onionmsg_payload,reply_path,first_node_id,point, tlvdata,obs2_onionmsg_payload,reply_path,blinding,point, diff --git a/wire/extracted_peer_05_newonion.patch b/wire/extracted_peer_05_newonion.patch index ed35699aa..b14d5471e 100644 --- a/wire/extracted_peer_05_newonion.patch +++ b/wire/extracted_peer_05_newonion.patch @@ -1,6 +1,6 @@ --- peer_wire.csv 2021-08-25 12:41:02.876254003 +0930 +++ peer_wire.csv.raw 2021-08-25 13:42:31.991693809 +0930 -@@ -320,3 +210,7 @@ +@@ -320,3 +210,11 @@ msgdata,gossip_timestamp_filter,chain_hash,chain_hash, msgdata,gossip_timestamp_filter,first_timestamp,u32, msgdata,gossip_timestamp_filter,timestamp_range,u32, @@ -8,3 +8,7 @@ +msgdata,obs2_onion_message,blinding,point, +msgdata,obs2_onion_message,len,u16, +msgdata,obs2_onion_message,onionmsg,byte,len ++msgtype,onion_message,513,option_onion_messages ++msgdata,onion_message,blinding,point, ++msgdata,onion_message,len,u16, ++msgdata,onion_message,onionmsg,byte,len diff --git a/wire/onion_wire.csv b/wire/onion_wire.csv index ca41fd885..2ac0c4cff 100644 --- a/wire/onion_wire.csv +++ b/wire/onion_wire.csv @@ -28,10 +28,36 @@ tlvtype,obs2_encmsg_tlvs,next_blinding,12 tlvdata,obs2_encmsg_tlvs,next_blinding,blinding,point, tlvtype,obs2_encmsg_tlvs,self_id,14 tlvdata,obs2_encmsg_tlvs,self_id,data,byte,... +tlvtype,tlv_payload,encrypted_recipient_data,10 +tlvdata,tlv_payload,encrypted_recipient_data,encrypted_data,byte,... +tlvtype,tlv_payload,blinding_point,12 +tlvdata,tlv_payload,blinding_point,blinding,point, +tlvtype,encrypted_data_tlv,padding,1 +tlvdata,encrypted_data_tlv,padding,padding,byte,... +tlvtype,encrypted_data_tlv,short_channel_id,2 +tlvdata,encrypted_data_tlv,short_channel_id,short_channel_id,short_channel_id, +tlvtype,encrypted_data_tlv,next_node_id,4 +tlvdata,encrypted_data_tlv,next_node_id,node_id,point, +tlvtype,encrypted_data_tlv,path_id,6 +tlvdata,encrypted_data_tlv,path_id,data,byte,... +tlvtype,encrypted_data_tlv,next_blinding_override,8 +tlvdata,encrypted_data_tlv,next_blinding_override,blinding,point, +tlvtype,onionmsg_payload,reply_path,2 +tlvdata,onionmsg_payload,reply_path,first_node_id,point, +tlvdata,onionmsg_payload,reply_path,blinding,point, +tlvdata,onionmsg_payload,reply_path,path,onionmsg_path,... +tlvtype,onionmsg_payload,encrypted_data_tlv,4 +tlvdata,onionmsg_payload,encrypted_data_tlv,encrypted_data_tlv,byte,... +tlvtype,onionmsg_payload,invoice_request,64 +tlvdata,onionmsg_payload,invoice_request,invoice_request,byte,... +tlvtype,onionmsg_payload,invoice,66 +tlvdata,onionmsg_payload,invoice,invoice,byte,... +tlvtype,onionmsg_payload,invoice_error,68 +tlvdata,onionmsg_payload,invoice_error,invoice_error,byte,... subtype,onionmsg_path subtypedata,onionmsg_path,node_id,point, subtypedata,onionmsg_path,enclen,u16, -subtypedata,onionmsg_path,enctlv,byte,enclen +subtypedata,onionmsg_path,encrypted_recipient_data,byte,enclen msgtype,invalid_realm,PERM|1 msgtype,temporary_node_failure,NODE|2 msgtype,permanent_node_failure,PERM|NODE|2 diff --git a/wire/peer_wire.c b/wire/peer_wire.c index 1a259da3f..aa3f3133e 100644 --- a/wire/peer_wire.c +++ b/wire/peer_wire.c @@ -34,6 +34,7 @@ static bool unknown_type(enum peer_wire t) case WIRE_REPLY_CHANNEL_RANGE: case WIRE_GOSSIP_TIMESTAMP_FILTER: case WIRE_OBS2_ONION_MESSAGE: + case WIRE_ONION_MESSAGE: case WIRE_TX_ADD_INPUT: case WIRE_TX_REMOVE_INPUT: case WIRE_TX_ADD_OUTPUT: @@ -63,6 +64,7 @@ bool is_msg_for_gossipd(const u8 *cursor) case WIRE_QUERY_CHANNEL_RANGE: case WIRE_REPLY_CHANNEL_RANGE: case WIRE_OBS2_ONION_MESSAGE: + case WIRE_ONION_MESSAGE: return true; case WIRE_WARNING: case WIRE_INIT: diff --git a/wire/peer_wire.csv b/wire/peer_wire.csv index 0a28459fa..4043c6350 100644 --- a/wire/peer_wire.csv +++ b/wire/peer_wire.csv @@ -332,3 +332,7 @@ msgtype,obs2_onion_message,387,option_onion_messages msgdata,obs2_onion_message,blinding,point, msgdata,obs2_onion_message,len,u16, msgdata,obs2_onion_message,onionmsg,byte,len +msgtype,onion_message,513,option_onion_messages +msgdata,onion_message,blinding,point, +msgdata,onion_message,len,u16, +msgdata,onion_message,onionmsg,byte,len