Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Offers compat fixes #5892

Merged
2 changes: 1 addition & 1 deletion ccan/README
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
CCAN imported from http://ccodearchive.net.

CCAN version: init-2548-gab87e56b
CCAN version: init-2549-gba79e21b
3 changes: 1 addition & 2 deletions ccan/ccan/tcon/tcon.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,7 @@
* It evaluates to @x so you can chain it.
*/
#define tcon_check_ptr(x, canary, expr) \
(sizeof(&(x)->_tcon[0].canary == (expr)) ? (x) : (x))

(sizeof((expr) ? (expr) : &(x)->_tcon[0].canary) ? (x) : (x))

/**
* tcon_type - the type within a container (or void *)
Expand Down
5 changes: 3 additions & 2 deletions common/blindedpath.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,9 @@ struct tlv_encrypted_data_tlv *decrypt_encrypted_data(const tal_t *ctx,

/* BOLT-onion-message #4:
*
* - if the `enctlv` is not a valid TLV...
* - MUST drop the message.
* - MUST return an error if `encrypted_recipient_data` does not decrypt
* using the blinding point as described in
* [Route Blinding](#route-blinding).
*/
/* Note: our parser consider nothing is a valid TLV, but decrypt_encmsg_raw
* returns NULL if it couldn't decrypt. */
Expand Down
5 changes: 3 additions & 2 deletions common/blindedpay.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
u8 **blinded_onion_hops(const tal_t *ctx,
struct amount_msat final_amount,
u32 final_cltv,
struct amount_msat total_amount,
const struct blinded_path *path)
{
u8 **onions = tal_arr(ctx, u8 *, tal_count(path->path));
Expand All @@ -25,12 +26,12 @@ u8 **blinded_onion_hops(const tal_t *ctx,
* - MUST include the `blinding_point` provided by the
* recipient in `current_blinding_point`
* - If it is the final node:
* - MUST include `amt_to_forward` and `outgoing_cltv_value`.
* - MUST include `total_amount_msat` when using `basic_mpp`.
* - MUST include `amt_to_forward`, `outgoing_cltv_value` and `total_amount_msat`.
* - MUST NOT include any other tlv field.
*/
onions[i] = onion_blinded_hop(onions,
final ? &final_amount : NULL,
final ? &total_amount : NULL,
final ? &final_cltv : NULL,
path->path[i]->encrypted_recipient_data,
first ? &path->blinding : NULL);
Expand Down
2 changes: 2 additions & 0 deletions common/blindedpay.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ struct blinded_path;
* @ctx: context to allocate from
* @final_amount: amount we want to reach the end
* @final_cltv: cltv we want to at end
* @total_amount: amount of all parts together.
* @payinfo: fee and other restriction info
*
* This calls onion_nonfinal_hop and onion_final_hop to create onion
Expand All @@ -20,6 +21,7 @@ struct blinded_path;
u8 **blinded_onion_hops(const tal_t *ctx,
struct amount_msat final_amount,
u32 final_cltv,
struct amount_msat total_amount,
const struct blinded_path *path);

#endif /* LIGHTNING_COMMON_BLINDEDPAY_H */
95 changes: 63 additions & 32 deletions common/onion_decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,54 @@
#include <common/sphinx.h>
#include <sodium/crypto_aead_chacha20poly1305.h>

/* BOLT-route-blinding #4:
* - If `encrypted_recipient_data` is present:
*...
* - If it is not the final node:
* - MUST return an error if the payload contains other tlv fields than
* `encrypted_recipient_data` and `current_blinding_point`.
*/
static bool check_nonfinal_tlv(const struct tlv_tlv_payload *tlv,
u64 *failtlvtype)
{
for (size_t i = 0; i < tal_count(tlv->fields); i++) {
switch (tlv->fields[i].numtype) {
case TLV_TLV_PAYLOAD_BLINDING_POINT:
case TLV_TLV_PAYLOAD_ENCRYPTED_RECIPIENT_DATA:
continue;
}
*failtlvtype = tlv->fields[i].numtype;
return false;
}
return true;
}

/* BOLT-route-blinding #4:
* - If `encrypted_recipient_data` is present:
*...
* - If it is the final node:
* - MUST return an error if the payload contains other tlv fields than
* `encrypted_recipient_data`, `current_blinding_point`, `amt_to_forward`,
* `outgoing_cltv_value` and `total_amount_msat`.
*/
static bool check_final_tlv(const struct tlv_tlv_payload *tlv,
u64 *failtlvtype)
{
for (size_t i = 0; i < tal_count(tlv->fields); i++) {
switch (tlv->fields[i].numtype) {
case TLV_TLV_PAYLOAD_ENCRYPTED_RECIPIENT_DATA:
case TLV_TLV_PAYLOAD_BLINDING_POINT:
case TLV_TLV_PAYLOAD_AMT_TO_FORWARD:
case TLV_TLV_PAYLOAD_OUTGOING_CLTV_VALUE:
case TLV_TLV_PAYLOAD_TOTAL_AMOUNT_MSAT:
continue;
}
*failtlvtype = tlv->fields[i].numtype;
return false;
}
return true;
}

static u64 ceil_div(u64 a, u64 b)
{
return (a + b - 1) / b;
Expand All @@ -23,18 +71,8 @@ static bool handle_blinded_forward(struct onion_payload *p,
{
u64 amt = amount_in.millisatoshis; /* Raw: allowed to wrap */

/* BOLT-route-blinding #4:
* - If it is not the final node:
* - MUST return an error if the payload contains other tlv fields
* than `encrypted_recipient_data` and `current_blinding_point`.
*/
for (size_t i = 0; i < tal_count(tlv->fields); i++) {
if (tlv->fields[i].numtype != TLV_TLV_PAYLOAD_BLINDING_POINT
&& tlv->fields[i].numtype != TLV_TLV_PAYLOAD_ENCRYPTED_RECIPIENT_DATA) {
*failtlvtype = tlv->fields[i].numtype;
return false;
}
}
if (!check_nonfinal_tlv(tlv, failtlvtype))
return false;

/* BOLT-route-blinding #4:
* - If it is not the final node:
Expand Down Expand Up @@ -84,26 +122,12 @@ static bool handle_blinded_terminal(struct onion_payload *p,
const struct tlv_encrypted_data_tlv *enc,
u64 *failtlvtype)
{
/* BOLT-route-blinding #4:
* - If it is the final node:
* - MUST return an error if the payload contains other tlv fields than
* `encrypted_recipient_data`, `current_blinding_point`, `amt_to_forward`,
* `outgoing_cltv_value` and `total_amount_msat`.
*/
for (size_t i = 0; i < tal_count(tlv->fields); i++) {
if (tlv->fields[i].numtype != TLV_TLV_PAYLOAD_BLINDING_POINT
&& tlv->fields[i].numtype != TLV_TLV_PAYLOAD_ENCRYPTED_RECIPIENT_DATA
&& tlv->fields[i].numtype != TLV_TLV_PAYLOAD_AMT_TO_FORWARD
&& tlv->fields[i].numtype != TLV_TLV_PAYLOAD_OUTGOING_CLTV_VALUE
&& tlv->fields[i].numtype != TLV_TLV_PAYLOAD_TOTAL_AMOUNT_MSAT) {
*failtlvtype = tlv->fields[i].numtype;
return false;
}
}
if (!check_final_tlv(tlv, failtlvtype))
return false;

/* BOLT-route-blinding #4:
* - MUST return an error if `amt_to_forward` or
* `outgoing_cltv_value` are not present.
* - MUST return an error if `amt_to_forward`, `outgoing_cltv_value`
* or `total_amount_msat` are not present.
* - MUST return an error if `amt_to_forward` is below what it expects
* for the payment.
*/
Expand All @@ -117,6 +141,11 @@ static bool handle_blinded_terminal(struct onion_payload *p,
return false;
}

if (!tlv->total_amount_msat) {
*failtlvtype = TLV_TLV_PAYLOAD_TOTAL_AMOUNT_MSAT;
return false;
}

p->amt_to_forward = amount_msat(*tlv->amt_to_forward);
p->outgoing_cltv = *tlv->outgoing_cltv_value;

Expand Down Expand Up @@ -151,6 +180,8 @@ struct onion_payload *onion_decode(const tal_t *ctx,
const u8 *cursor = rs->raw_payload;
size_t max = tal_bytelen(cursor), len;

p->final = (rs->nextcase == ONION_END);

/* BOLT-remove-legacy-onion #4:
* 1. type: `hop_payloads`
* 2. data:
Expand Down Expand Up @@ -276,7 +307,7 @@ struct onion_payload *onion_decode(const tal_t *ctx,
goto field_bad;
}

if (rs->nextcase == ONION_FORWARD) {
if (!p->final) {
if (!handle_blinded_forward(p, amount_in, cltv_expiry,
p->tlv, enc, failtlvtype))
goto field_bad;
Expand Down Expand Up @@ -333,7 +364,7 @@ struct onion_payload *onion_decode(const tal_t *ctx,
* - For every non-final node:
* - MUST include `short_channel_id`
*/
if (rs->nextcase == ONION_FORWARD) {
if (!p->final) {
if (!p->tlv->short_channel_id) {
*failtlvtype = TLV_TLV_PAYLOAD_SHORT_CHANNEL_ID;
goto field_bad;
Expand Down
6 changes: 6 additions & 0 deletions common/onion_encode.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ u8 *onion_final_hop(const tal_t *ctx,

u8 *onion_blinded_hop(const tal_t *ctx,
const struct amount_msat *amt_to_forward,
const struct amount_msat *total_amount_msat,
const u32 *outgoing_cltv_value,
const u8 *enctlv,
const struct pubkey *blinding)
Expand All @@ -114,6 +115,11 @@ u8 *onion_blinded_hop(const tal_t *ctx,
= cast_const(u64 *,
&amt_to_forward->millisatoshis); /* Raw: TLV convert */
}
if (total_amount_msat) {
tlv->total_amount_msat
= cast_const(u64 *,
&total_amount_msat->millisatoshis); /* Raw: TLV convert */
}
tlv->outgoing_cltv_value = cast_const(u32 *, outgoing_cltv_value);
tlv->encrypted_recipient_data = cast_const(u8 *, enctlv);
tlv->blinding_point = cast_const(struct pubkey *, blinding);
Expand Down
5 changes: 4 additions & 1 deletion common/onion_encode.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ enum onion_payload_type {

struct onion_payload {
enum onion_payload_type type;
/* Is this the final hop? */
bool final;

struct amount_msat amt_to_forward;
u32 outgoing_cltv;
Expand Down Expand Up @@ -51,8 +53,9 @@ u8 *onion_final_hop(const tal_t *ctx,
* generic interface, as used by blindedpay.h */
u8 *onion_blinded_hop(const tal_t *ctx,
const struct amount_msat *amt_to_forward,
const struct amount_msat *total_amount_msat,
const u32 *outgoing_cltv_value,
const u8 *enctlv,
const struct pubkey *blinding)
NON_NULL_ARGS(4);
NON_NULL_ARGS(5);
#endif /* LIGHTNING_COMMON_ONION_ENCODE_H */
32 changes: 18 additions & 14 deletions common/onion_message_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,25 +50,19 @@ static bool decrypt_forwarding_onionmsg(const struct pubkey *blinding,
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 the `encrypted_data_tlv` contains `path_id`:
* - MUST ignore the message.
*/
if (!encmsg->next_node_id)
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 the `enctlv` contains `path_id`:
* - MUST drop the message.
* - SHOULD forward the message using `onion_message` to the next peer
* indicated by `next_node_id`.
*/
if (encmsg->path_id)
if (!encmsg->next_node_id)
return false;

*next_node = *encmsg->next_node_id;
Expand Down Expand Up @@ -145,7 +139,6 @@ bool onion_message_parse(const tal_t *ctx,
tal_hex(tmpctx, rs->raw_payload));
return false;
}

if (rs->nextcase == ONION_END) {
*next_onion_msg = NULL;
*final_om = tal_steal(ctx, om);
Expand All @@ -167,6 +160,18 @@ bool onion_message_parse(const tal_t *ctx,

*final_om = NULL;

/* BOLT-onion-message #4:
* - 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) {
status_peer_debug(peer,
"onion_message_parse: "
"disallowed tlv field");
return false;
}

/* This fails as expected if no enctlv. */
if (!decrypt_forwarding_onionmsg(blinding, &ss, om->encrypted_recipient_data, next_node_id,
&next_blinding)) {
Expand All @@ -175,7 +180,6 @@ bool onion_message_parse(const tal_t *ctx,
tal_hex(tmpctx, om->encrypted_recipient_data));
return false;
}

*next_onion_msg = towire_onion_message(ctx,
&next_blinding,
serialize_onionpacket(tmpctx, rs->next));
Expand Down
23 changes: 14 additions & 9 deletions common/test/run-onion-message-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ void ecdh(const struct pubkey *point, struct secret *ss)
abort();
}

/* This established by trial and error! */
#define LARGEST_TLV_SIZE 70
/* This established by trial and error. */
#define LARGEST_DAVE_TLV_SIZE 42

/* Generic, ugly, function to calc encrypted_recipient_data,
alias and next blinding, and print out JSON */
Expand Down Expand Up @@ -175,17 +175,22 @@ static u8 *add_hop(const char *name,
enctlv = tal_arr(tmpctx, u8, 0);
towire_tlv_encrypted_data_tlv(&enctlv, tlv);

/* Now create padding, and reencode */
if (tal_bytelen(enctlv) + tal_bytelen(additional) != LARGEST_TLV_SIZE)
/* Now create padding (in Dave's path) */
if (tal_bytelen(enctlv) + tal_bytelen(additional)
< LARGEST_DAVE_TLV_SIZE) {
/* Add padding: T and L take 2 bytes, even before V */
assert(tal_bytelen(enctlv) + tal_bytelen(additional) + 2
<= LARGEST_DAVE_TLV_SIZE);
tlv->padding = tal_arrz(tlv, u8,
LARGEST_TLV_SIZE
LARGEST_DAVE_TLV_SIZE
- tal_bytelen(enctlv)
- tal_bytelen(additional)
- 2);
- tal_bytelen(additional) - 2);
}
enctlv = tal_arr(tmpctx, u8, 0);
towire_tlv_encrypted_data_tlv(&enctlv, tlv);
towire(&enctlv, additional, tal_bytelen(additional));
assert(tal_bytelen(enctlv) == LARGEST_TLV_SIZE);
if (!override_blinding)
assert(tal_bytelen(enctlv) == LARGEST_DAVE_TLV_SIZE);

json_start("tlvs", '{');
if (tlv->padding)
Expand Down Expand Up @@ -332,7 +337,7 @@ int main(int argc, char *argv[])
sphinx_path->session_key = &session_key;

/* BOLT-onion-message #4:
* - SHOULD set `len` to 1366 or 32834.
* - SHOULD set `onion_message_packet` `len` to 1366 or 32834.
*/
op = create_onionpacket(tmpctx, sphinx_path, ROUTING_INFO_SIZE,
&path_secrets);
Expand Down
Loading