diff --git a/common/blindedpath.c b/common/blindedpath.c index 918aef3bf..46176eab1 100644 --- a/common/blindedpath.c +++ b/common/blindedpath.c @@ -107,15 +107,20 @@ static u8 *enctlv_from_encmsg_raw(const tal_t *ctx, return ret; } -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 *encrypt_tlv_encrypted_data(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) { + struct privkey unused; u8 *encmsg_raw = tal_arr(NULL, u8, 0); towire_tlv_encrypted_data_tlv(&encmsg_raw, encmsg); + + /* last hop doesn't care about next_blinding */ + if (!next_blinding) + next_blinding = &unused; return enctlv_from_encmsg_raw(ctx, blinding, node, take(encmsg_raw), next_blinding, node_alias); } @@ -253,52 +258,3 @@ void blindedpath_next_blinding(const struct tlv_encrypted_data_tlv *enc, blinding_next_pubkey(blinding, &h, next_blinding); } } - -u8 *create_enctlv(const tal_t *ctx, - const struct privkey *blinding, - const struct pubkey *node, - const struct pubkey *next_node, - const struct short_channel_id *next_scid, - size_t padlen, - const struct pubkey *next_blinding_override, - const struct tlv_encrypted_data_tlv_payment_relay *payment_relay TAKES, - const struct tlv_encrypted_data_tlv_payment_constraints *payment_constraints TAKES, - const u8 *allowed_features TAKES, - 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); - encmsg->payment_relay = tal_dup_or_null(encmsg, struct tlv_encrypted_data_tlv_payment_relay, - payment_relay); - encmsg->payment_constraints = tal_dup_or_null(encmsg, struct tlv_encrypted_data_tlv_payment_constraints, - payment_constraints); - encmsg->allowed_features = tal_dup_talarr(encmsg, u8, allowed_features); - - 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, - const u8 *allowed_features TAKES, - 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); - encmsg->allowed_features = tal_dup_talarr(encmsg, u8, allowed_features); - - return enctlv_from_encmsg(ctx, blinding, final_node, encmsg, - &unused_next_blinding, node_alias); -} diff --git a/common/blindedpath.h b/common/blindedpath.h index 6827d10a5..7df0dc2aa 100644 --- a/common/blindedpath.h +++ b/common/blindedpath.h @@ -10,61 +10,29 @@ struct pubkey; struct privkey; struct secret; struct short_channel_id; +struct tlv_encrypted_data_tlv; struct tlv_encrypted_data_tlv_payment_constraints; struct tlv_encrypted_data_tlv_payment_relay; /** - * create_enctlv - Encrypt an encmsg to form an enctlv. + * encrypt_tlv_encrypted_data - Encrypt a tlv_encrypted_data_tlv. * @ctx: tal context * @blinding: e(i), the blinding secret * @node: the pubkey of the node to encrypt for - * @next_node: the pubkey of the next node, to place in enctlv - * @next_scid: the short_channel_id to the next node, to place in enctlv - * @padlen: if non-zero, the bytes of padding to add (also adds 2 byte padding hdr) - * @next_blinding_override: the optional blinding point to place in enctlv - * @payment_relay: optional payment_relay tlv - * @payment_constraints: optional payment_constraints tlv - * @allowed_features: optional allowed_features array - * @next_blinding: (out) e(i+1), the next blinding secret. + * @tlv: the message to encrypt. + * @next_blinding: (out) e(i+1), the next blinding secret (optional) * @node_alias: (out) the blinded pubkey of the node to tell the recipient. * - * Exactly one of next_node and next_scid must be non-NULL. - * Returns the enctlv blob, or NULL if the secret is invalid. + * You create a blinding secret using randombytes_buf(), then call this + * iteratively for each node in the path. */ -u8 *create_enctlv(const tal_t *ctx, - const struct privkey *blinding, - const struct pubkey *node, - const struct pubkey *next_node, - const struct short_channel_id *next_scid, - size_t padlen, - const struct pubkey *next_blinding_override, - const struct tlv_encrypted_data_tlv_payment_relay *payment_relay TAKES, - const struct tlv_encrypted_data_tlv_payment_constraints *payment_constraints TAKES, - const u8 *allowed_features TAKES, - struct privkey *next_blinding, - struct pubkey *node_alias) - NON_NULL_ARGS(2, 3, 11, 12); - -/** - * create_final_enctlv - Encrypt an encmsg to form the final enctlv. - * @ctx: tal context - * @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) - * @allowed_features: optional allowed_features array - * @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_final_enctlv(const tal_t *ctx, - const struct privkey *blinding, - const struct pubkey *final_node, - size_t padlen, - const struct secret *path_id, - const u8 *allowed_features TAKES, - struct pubkey *node_alias) - NON_NULL_ARGS(2, 3, 7); +u8 *encrypt_tlv_encrypted_data(const tal_t *ctx, + const struct privkey *blinding, + const struct pubkey *node, + const struct tlv_encrypted_data_tlv *tlv, + struct privkey *next_blinding, + struct pubkey *node_alias) + NON_NULL_ARGS(2, 3, 4, 6); /** * unblind_onion - tweak onion epheremeral key so we can decode it with ours. diff --git a/common/onion_decode.c b/common/onion_decode.c index 4d7b81a6a..680a245b2 100644 --- a/common/onion_decode.c +++ b/common/onion_decode.c @@ -373,4 +373,3 @@ field_bad: *failtlvtype); return tal_free(p); } - diff --git a/common/test/run-blindedpath_enctlv.c b/common/test/run-blindedpath_enctlv.c index 58d28c666..fd88d7cbb 100644 --- a/common/test/run-blindedpath_enctlv.c +++ b/common/test/run-blindedpath_enctlv.c @@ -140,6 +140,7 @@ int main(int argc, char *argv[]) struct pubkey alice_id, bob_id, carol_id, dave_id, blinding_pub, override_blinding_pub, alias; struct secret self_id; u8 *enctlv; + struct tlv_encrypted_data_tlv *tlv; common_setup(argv[0]); @@ -171,8 +172,10 @@ int main(int argc, char *argv[]) "\t},\n", type_to_string(tmpctx, struct pubkey, &bob_id)); - enctlv = create_enctlv(tmpctx, &blinding, &alice_id, &bob_id, NULL, - 0, NULL, NULL, NULL, NULL, &blinding, &alias); + tlv = tlv_encrypted_data_tlv_new(tmpctx); + tlv->next_node_id = &bob_id; + enctlv = encrypt_tlv_encrypted_data(tmpctx, &blinding, &alice_id, tlv, + &blinding, &alias); printf("\t\"encrypted_recipient_data_hex\": \"%s\"\n" "},\n", tal_hex(tmpctx, enctlv)); @@ -201,9 +204,11 @@ int main(int argc, char *argv[]) type_to_string(tmpctx, struct pubkey, &carol_id), type_to_string(tmpctx, struct privkey, &override_blinding)); - enctlv = create_enctlv(tmpctx, &blinding, &bob_id, &carol_id, NULL, - 0, &override_blinding_pub, NULL, NULL, NULL, - &blinding, &alias); + tlv = tlv_encrypted_data_tlv_new(tmpctx); + tlv->next_node_id = &carol_id; + tlv->next_blinding_override = &override_blinding_pub; + enctlv = encrypt_tlv_encrypted_data(tmpctx, &blinding, &bob_id, tlv, + &blinding, &alias); printf("\t\"encrypted_recipient_data_hex\": \"%s\"\n" "},\n", tal_hex(tmpctx, enctlv)); @@ -231,8 +236,11 @@ int main(int argc, char *argv[]) type_to_string(tmpctx, struct pubkey, &dave_id), tal_hex(tmpctx, tal_arrz(tmpctx, u8, 35))); - enctlv = create_enctlv(tmpctx, &blinding, &carol_id, &dave_id, NULL, - 35, NULL, NULL, NULL, NULL, &blinding, &alias); + tlv = tlv_encrypted_data_tlv_new(tmpctx); + tlv->padding = tal_arrz(tlv, u8, 35); + tlv->next_node_id = &dave_id; + enctlv = encrypt_tlv_encrypted_data(tmpctx, &blinding, &carol_id, tlv, + &blinding, &alias); printf("\t\"encrypted_recipient_data_hex\": \"%s\"\n" "},\n", tal_hex(tmpctx, enctlv)); @@ -256,8 +264,11 @@ int main(int argc, char *argv[]) "\t},\n", type_to_string(tmpctx, struct secret, &self_id)); - enctlv = create_final_enctlv(tmpctx, &blinding, &dave_id, - 0, &self_id, NULL, &alias); + tlv = tlv_encrypted_data_tlv_new(tmpctx); + tlv->path_id = tal_dup_arr(tlv, u8, + self_id.data, ARRAY_SIZE(self_id.data), 0); + enctlv = encrypt_tlv_encrypted_data(tmpctx, &blinding, &dave_id, tlv, + NULL, &alias); printf("\t\"encrypted_recipient_data_hex\": \"%s\"\n", tal_hex(tmpctx, enctlv)); diff --git a/common/test/run-blindedpath_onion.c b/common/test/run-blindedpath_onion.c index 94e03de96..5aa521b25 100644 --- a/common/test/run-blindedpath_onion.c +++ b/common/test/run-blindedpath_onion.c @@ -154,6 +154,7 @@ int main(int argc, char *argv[]) struct privkey nodekey[4], blinding[4], override_blinding; struct pubkey id[4], blinding_pub[4], override_blinding_pub, alias[4]; struct secret self_id; + struct tlv_encrypted_data_tlv *tlv[4]; u8 *enctlv[4]; u8 *onionmsg_tlv[4]; u8 *omsg; @@ -173,35 +174,54 @@ int main(int argc, char *argv[]) memset(&blinding[ALICE], 5, sizeof(blinding[ALICE])); pubkey_from_privkey(&blinding[ALICE], &blinding_pub[ALICE]); - enctlv[ALICE] = create_enctlv(tmpctx, &blinding[ALICE], - &id[ALICE], &id[BOB], NULL, - 0, NULL, NULL, NULL, NULL, - &blinding[BOB], &alias[ALICE]); + tlv[ALICE] = tlv_encrypted_data_tlv_new(tmpctx); + tlv[ALICE]->next_node_id = &id[BOB]; + enctlv[ALICE] = encrypt_tlv_encrypted_data(tmpctx, + &blinding[ALICE], + &id[ALICE], tlv[ALICE], + &blinding[BOB], + &alias[ALICE]); pubkey_from_privkey(&blinding[BOB], &blinding_pub[BOB]); /* We override blinding for Carol. */ memset(&override_blinding, 7, sizeof(override_blinding)); pubkey_from_privkey(&override_blinding, &override_blinding_pub); - enctlv[BOB] = create_enctlv(tmpctx, &blinding[BOB], - &id[BOB], &id[CAROL], NULL, - 0, &override_blinding_pub, NULL, NULL, NULL, - &blinding[CAROL], &alias[BOB]); + + tlv[BOB] = tlv_encrypted_data_tlv_new(tmpctx); + tlv[BOB]->next_node_id = &id[CAROL]; + tlv[BOB]->next_blinding_override = &override_blinding_pub; + enctlv[BOB] = encrypt_tlv_encrypted_data(tmpctx, + &blinding[BOB], + &id[BOB], tlv[BOB], + &blinding[CAROL], + &alias[BOB]); /* That replaced the blinding */ blinding[CAROL] = override_blinding; blinding_pub[CAROL] = override_blinding_pub; - enctlv[CAROL] = create_enctlv(tmpctx, &blinding[CAROL], - &id[CAROL], &id[DAVE], NULL, - 35, NULL, NULL, NULL, NULL, - &blinding[DAVE], &alias[CAROL]); + tlv[CAROL] = tlv_encrypted_data_tlv_new(tmpctx); + tlv[CAROL]->next_node_id = &id[DAVE]; + tlv[CAROL]->padding = tal_arrz(tlv[CAROL], u8, 35); + enctlv[CAROL] = encrypt_tlv_encrypted_data(tmpctx, + &blinding[CAROL], + &id[CAROL], tlv[CAROL], + &blinding[DAVE], + &alias[CAROL]); for (size_t i = 0; i < sizeof(self_id); i++) self_id.data[i] = i+1; - enctlv[DAVE] = create_final_enctlv(tmpctx, &blinding[DAVE], &id[DAVE], - 0, &self_id, NULL, &alias[DAVE]); + tlv[DAVE] = tlv_encrypted_data_tlv_new(tmpctx); + tlv[DAVE]->path_id = tal_dup_arr(tlv[DAVE], u8, + self_id.data, ARRAY_SIZE(self_id.data), + 0); + enctlv[DAVE] = encrypt_tlv_encrypted_data(tmpctx, + &blinding[DAVE], + &id[DAVE], tlv[DAVE], + NULL, + &alias[DAVE]); pubkey_from_privkey(&blinding[DAVE], &blinding_pub[DAVE]); /* Create an onion which encodes this. */ diff --git a/lightningd/onion_message.c b/lightningd/onion_message.c index dbcf1b99b..a70f7ba7f 100644 --- a/lightningd/onion_message.c +++ b/lightningd/onion_message.c @@ -285,6 +285,7 @@ static struct command_result *json_blindedpath(struct command *cmd, struct blinded_path *path; size_t nhops; struct json_stream *response; + struct tlv_encrypted_data_tlv *tlv; if (!param(cmd, buffer, params, p_req("ids", param_pubkeys, &ids), @@ -319,29 +320,33 @@ static struct command_result *json_blindedpath(struct command *cmd, blinding_iter = first_blinding; for (size_t i = 0; i < nhops - 1; i++) { path->path[i] = tal(path->path, struct onionmsg_hop); + + tlv = tlv_encrypted_data_tlv_new(tmpctx); + tlv->next_node_id = &ids[i+1]; + /* FIXME: Pad? */ + path->path[i]->encrypted_recipient_data - = create_enctlv(path->path[i], - &blinding_iter, - &ids[i], - &ids[i+1], NULL, - /* FIXME: Pad? */ - 0, - NULL, NULL, NULL, NULL, - &blinding_iter, - &path->path[i]->blinded_node_id); + = encrypt_tlv_encrypted_data(path->path[i], + &blinding_iter, + &ids[i], + tlv, + &blinding_iter, + &path->path[i]->blinded_node_id); } /* FIXME: Add padding! */ path->path[nhops-1] = tal(path->path, struct onionmsg_hop); + + tlv = tlv_encrypted_data_tlv_new(tmpctx); + tlv->path_id = (u8 *)tal_dup(tlv, struct secret, + &cmd->ld->onion_reply_secret); path->path[nhops-1]->encrypted_recipient_data - = create_final_enctlv(path->path[nhops-1], - &blinding_iter, - &ids[nhops-1], - /* FIXME: Pad? */ - 0, - &cmd->ld->onion_reply_secret, - NULL, - &path->path[nhops-1]->blinded_node_id); + = encrypt_tlv_encrypted_data(path->path[nhops-1], + &blinding_iter, + &ids[nhops-1], + tlv, + NULL, + &path->path[nhops-1]->blinded_node_id); response = json_stream_success(cmd); json_add_blindedpath(response, "blindedpath", path); diff --git a/plugins/fetchinvoice.c b/plugins/fetchinvoice.c index 8d3d41e9b..b887a274f 100644 --- a/plugins/fetchinvoice.c +++ b/plugins/fetchinvoice.c @@ -619,6 +619,7 @@ send_modern_message(struct command *cmd, size_t nhops = tal_count(sent->path); struct tlv_onionmsg_tlv **payloads; struct out_req *req; + struct tlv_encrypted_data_tlv *tlv; /* Now create enctlvs for *forward* path. */ randombytes_buf(&blinding_iter, sizeof(blinding_iter)); @@ -634,25 +635,30 @@ send_modern_message(struct command *cmd, for (size_t i = 1; i < nhops - 1; i++) { payloads[i] = tlv_onionmsg_tlv_new(payloads); - payloads[i]->encrypted_recipient_data = create_enctlv(payloads[i], - &blinding_iter, - &sent->path[i], - &sent->path[i+1], - NULL, - /* FIXME: Pad? */ - 0, - NULL, NULL, NULL, NULL, - &blinding_iter, - &node_alias[i]); + + tlv = tlv_encrypted_data_tlv_new(tmpctx); + tlv->next_node_id = &sent->path[i+1]; + /* FIXME: Pad? */ + + payloads[i]->encrypted_recipient_data + = encrypt_tlv_encrypted_data(payloads[i], + &blinding_iter, + &sent->path[i], + tlv, + &blinding_iter, + &node_alias[i]); } /* Final payload contains the actual data. */ payloads[nhops-1] = sending->payload; /* We don't include enctlv in final, but it gives us final alias */ - if (!create_final_enctlv(tmpctx, &blinding_iter, &sent->path[nhops-1], - /* FIXME: Pad? */ 0, - NULL, NULL, - &node_alias[nhops-1])) { + tlv = tlv_encrypted_data_tlv_new(tmpctx); + if (!encrypt_tlv_encrypted_data(tmpctx, + &blinding_iter, + &sent->path[nhops-1], + tlv, + NULL, + &node_alias[nhops-1])) { /* Should not happen! */ return command_fail(cmd, LIGHTNINGD, "Could create final enctlv"); @@ -668,12 +674,12 @@ send_modern_message(struct command *cmd, json_add_pubkey(req->js, "blinding", &fwd_blinding); json_array_start(req->js, "hops"); for (size_t i = 1; i < nhops; i++) { - u8 *tlv; + u8 *tlvbin; json_object_start(req->js, NULL); json_add_pubkey(req->js, "id", &node_alias[i]); - tlv = tal_arr(tmpctx, u8, 0); - towire_tlv_onionmsg_tlv(&tlv, payloads[i]); - json_add_hex_talarr(req->js, "tlv", tlv); + tlvbin = tal_arr(tmpctx, u8, 0); + towire_tlv_onionmsg_tlv(&tlvbin, payloads[i]); + json_add_hex_talarr(req->js, "tlv", tlvbin); json_object_end(req->js); } json_array_end(req->js);