2022-10-17 02:44:39 +02:00
|
|
|
/* Caller does fromwire_onion_message(), this does the rest. */
|
|
|
|
#include "config.h"
|
|
|
|
#include <assert.h>
|
2024-07-10 04:52:19 +02:00
|
|
|
#include <ccan/tal/str/str.h>
|
2022-10-17 02:44:39 +02:00
|
|
|
#include <common/blindedpath.h>
|
|
|
|
#include <common/ecdh.h>
|
|
|
|
#include <common/onion_message_parse.h>
|
|
|
|
#include <common/sphinx.h>
|
|
|
|
#include <common/status.h>
|
|
|
|
#include <common/utils.h>
|
|
|
|
#include <wire/onion_wire.h>
|
|
|
|
#include <wire/peer_wire.h>
|
|
|
|
|
|
|
|
static bool decrypt_final_onionmsg(const tal_t *ctx,
|
|
|
|
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;
|
|
|
|
|
|
|
|
if (!blindedpath_get_alias(ss, my_id, alias))
|
|
|
|
return false;
|
|
|
|
|
2024-10-14 18:03:49 +02:00
|
|
|
encmsg = decrypt_encrypted_data(tmpctx, ss, enctlv);
|
2022-10-17 02:44:39 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-10-14 18:03:49 +02:00
|
|
|
static bool decrypt_forwarding_onionmsg(const struct pubkey *path_key,
|
2022-10-17 02:44:39 +02:00
|
|
|
const struct secret *ss,
|
|
|
|
const u8 *enctlv,
|
2024-07-10 04:55:49 +02:00
|
|
|
struct sciddir_or_pubkey *next_node,
|
2024-10-14 18:03:49 +02:00
|
|
|
struct pubkey *next_path_key)
|
2022-10-17 02:44:39 +02:00
|
|
|
{
|
|
|
|
struct tlv_encrypted_data_tlv *encmsg;
|
|
|
|
|
2024-10-14 18:03:49 +02:00
|
|
|
encmsg = decrypt_encrypted_data(tmpctx, ss, enctlv);
|
2022-10-17 02:44:39 +02:00
|
|
|
if (!encmsg)
|
|
|
|
return false;
|
|
|
|
|
2024-03-18 04:01:06 +01:00
|
|
|
/* BOLT #4:
|
2022-10-17 02:44:39 +02:00
|
|
|
* - if it is not the final node according to the onion encryption:
|
|
|
|
*...
|
2023-01-12 04:55:38 +01:00
|
|
|
* - if the `encrypted_data_tlv` contains `path_id`:
|
|
|
|
* - MUST ignore the message.
|
2022-10-17 02:44:39 +02:00
|
|
|
*/
|
2023-01-12 04:55:38 +01:00
|
|
|
if (encmsg->path_id)
|
2022-10-17 02:44:39 +02:00
|
|
|
return false;
|
|
|
|
|
2024-07-10 04:55:49 +02:00
|
|
|
/* BOLT-offers #4:
|
|
|
|
* - if it is not the final node according to the onion encryption:
|
|
|
|
*...
|
|
|
|
* - if `next_node_id` is present:
|
|
|
|
* - the *next peer* is the peer with that node id.
|
|
|
|
* - otherwise, if `short_channel_id` is present and corresponds to an announced short_channel_id or a local alias for a channel:
|
|
|
|
* - the *next peer* is the peer at the other end of that channel.
|
|
|
|
* - otherwise:
|
|
|
|
* - MUST ignore the message.
|
2022-10-17 02:44:39 +02:00
|
|
|
*/
|
2024-07-10 04:55:49 +02:00
|
|
|
if (encmsg->next_node_id)
|
|
|
|
sciddir_or_pubkey_from_pubkey(next_node, encmsg->next_node_id);
|
|
|
|
else if (encmsg->short_channel_id) {
|
|
|
|
/* This is actually scid, not sciddir, but the type is convenient! */
|
|
|
|
struct short_channel_id_dir scidd;
|
|
|
|
scidd.scid = *encmsg->short_channel_id;
|
|
|
|
scidd.dir = 0;
|
|
|
|
sciddir_or_pubkey_from_scidd(next_node, &scidd);
|
|
|
|
} else
|
2022-10-17 02:44:39 +02:00
|
|
|
return false;
|
|
|
|
|
2024-10-14 18:03:49 +02:00
|
|
|
blindedpath_next_path_key(encmsg, path_key, ss, next_path_key);
|
2022-10-17 02:44:39 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns false on failure */
|
2024-07-10 04:52:19 +02:00
|
|
|
const char *onion_message_parse(const tal_t *ctx,
|
|
|
|
const u8 *onion_message_packet,
|
2024-10-15 01:24:26 +02:00
|
|
|
const struct pubkey *path_key,
|
2024-07-10 04:52:19 +02:00
|
|
|
const struct pubkey *me,
|
|
|
|
u8 **next_onion_msg,
|
2024-07-10 04:55:49 +02:00
|
|
|
struct sciddir_or_pubkey *next_node,
|
2024-07-10 04:52:19 +02:00
|
|
|
struct tlv_onionmsg_tlv **final_om,
|
|
|
|
struct pubkey *final_alias,
|
|
|
|
struct secret **final_path_id)
|
2022-10-17 02:44:39 +02:00
|
|
|
{
|
|
|
|
enum onion_wire badreason;
|
|
|
|
struct onionpacket *op;
|
|
|
|
struct pubkey ephemeral;
|
|
|
|
struct route_step *rs;
|
|
|
|
struct tlv_onionmsg_tlv *om;
|
|
|
|
struct secret ss, onion_ss;
|
|
|
|
const u8 *cursor;
|
|
|
|
size_t max, maxlen;
|
|
|
|
|
|
|
|
/* We unwrap the onion now. */
|
|
|
|
op = parse_onionpacket(tmpctx,
|
|
|
|
onion_message_packet,
|
|
|
|
tal_bytelen(onion_message_packet),
|
|
|
|
&badreason);
|
|
|
|
if (!op) {
|
2024-07-10 04:52:19 +02:00
|
|
|
return tal_fmt(ctx, "onion_message_parse: can't parse onionpacket: %s",
|
|
|
|
onion_wire_name(badreason));
|
2022-10-17 02:44:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ephemeral = op->ephemeralkey;
|
2024-10-15 01:24:26 +02:00
|
|
|
if (!unblind_onion(path_key, ecdh, &ephemeral, &ss)) {
|
2024-07-10 04:52:19 +02:00
|
|
|
return tal_fmt(ctx, "onion_message_parse: can't unblind onionpacket");
|
2022-10-17 02:44:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Now get onion shared secret and parse it. */
|
|
|
|
ecdh(&ephemeral, &onion_ss);
|
2024-07-09 10:37:44 +02:00
|
|
|
rs = process_onionpacket(tmpctx, op, &onion_ss, NULL, 0);
|
2022-10-17 02:44:39 +02:00
|
|
|
if (!rs) {
|
2024-07-10 04:52:19 +02:00
|
|
|
return tal_fmt(ctx, "onion_message_parse: can't process onionpacket ss=%s",
|
|
|
|
fmt_secret(tmpctx, &onion_ss));
|
2022-10-17 02:44:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* The raw payload is prepended with length in the modern onion. */
|
|
|
|
cursor = rs->raw_payload;
|
|
|
|
max = tal_bytelen(rs->raw_payload);
|
|
|
|
maxlen = fromwire_bigsize(&cursor, &max);
|
|
|
|
if (!cursor) {
|
2024-07-10 04:52:19 +02:00
|
|
|
return tal_fmt(ctx, "onion_message_parse: Invalid hop payload %s",
|
|
|
|
tal_hex(tmpctx, rs->raw_payload));
|
2022-10-17 02:44:39 +02:00
|
|
|
}
|
|
|
|
if (maxlen > max) {
|
2024-07-10 04:52:19 +02:00
|
|
|
return tal_fmt(ctx, "onion_message_parse: overlong hop payload %s",
|
|
|
|
tal_hex(tmpctx, rs->raw_payload));
|
2022-10-17 02:44:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
om = fromwire_tlv_onionmsg_tlv(tmpctx, &cursor, &maxlen);
|
|
|
|
if (!om) {
|
2024-07-10 04:52:19 +02:00
|
|
|
return tal_fmt(ctx, "onion_message_parse: invalid onionmsg_tlv %s",
|
|
|
|
tal_hex(tmpctx, rs->raw_payload));
|
2022-10-17 02:44:39 +02:00
|
|
|
}
|
|
|
|
if (rs->nextcase == ONION_END) {
|
|
|
|
*next_onion_msg = NULL;
|
|
|
|
*final_om = tal_steal(ctx, om);
|
|
|
|
/* Final enctlv is actually optional */
|
|
|
|
if (!om->encrypted_recipient_data) {
|
|
|
|
*final_alias = *me;
|
|
|
|
*final_path_id = NULL;
|
2024-10-15 01:24:26 +02:00
|
|
|
} else if (!decrypt_final_onionmsg(ctx, &ss,
|
2022-10-17 02:44:39 +02:00
|
|
|
om->encrypted_recipient_data, me,
|
|
|
|
final_alias,
|
|
|
|
final_path_id)) {
|
2024-07-10 04:52:19 +02:00
|
|
|
return tal_fmt(ctx,
|
2022-10-17 02:44:39 +02:00
|
|
|
"onion_message_parse: failed to decrypt encrypted_recipient_data"
|
|
|
|
" %s", tal_hex(tmpctx, om->encrypted_recipient_data));
|
|
|
|
}
|
|
|
|
} else {
|
2024-10-15 01:24:26 +02:00
|
|
|
struct pubkey next_path_key;
|
2022-10-17 02:44:39 +02:00
|
|
|
|
|
|
|
*final_om = NULL;
|
|
|
|
|
2024-03-18 04:01:06 +01:00
|
|
|
/* BOLT #4:
|
2023-01-12 04:55:38 +01:00
|
|
|
* - if it is not the final node according to the onion encryption:
|
|
|
|
* - if the `onionmsg_tlv` contains other tlv fields than `encrypted_recipient_data`:
|
|
|
|
* - MUST ignore the message.
|
|
|
|
*/
|
|
|
|
if (tal_count(om->fields) != 1) {
|
2024-07-10 04:52:19 +02:00
|
|
|
return tal_fmt(ctx, "onion_message_parse: disallowed tlv field");
|
2023-01-12 04:55:38 +01:00
|
|
|
}
|
|
|
|
|
2022-10-17 02:44:39 +02:00
|
|
|
/* This fails as expected if no enctlv. */
|
2024-10-15 01:24:26 +02:00
|
|
|
if (!decrypt_forwarding_onionmsg(path_key, &ss, om->encrypted_recipient_data, next_node,
|
|
|
|
&next_path_key)) {
|
2024-07-10 04:52:19 +02:00
|
|
|
return tal_fmt(ctx,
|
|
|
|
"onion_message_parse: invalid encrypted_recipient_data %s",
|
|
|
|
tal_hex(tmpctx, om->encrypted_recipient_data));
|
2022-10-17 02:44:39 +02:00
|
|
|
}
|
|
|
|
*next_onion_msg = towire_onion_message(ctx,
|
2024-10-15 01:24:26 +02:00
|
|
|
&next_path_key,
|
2022-10-17 02:44:39 +02:00
|
|
|
serialize_onionpacket(tmpctx, rs->next));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Exactly one is set */
|
|
|
|
assert(!*next_onion_msg + !*final_om == 1);
|
2024-07-10 04:52:19 +02:00
|
|
|
return NULL;
|
2022-10-17 02:44:39 +02:00
|
|
|
}
|