From 24984ec680a2e614c43cef8bc1b6da666c8208f0 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 12 Mar 2020 10:29:01 +1030 Subject: [PATCH] common/sphinx: add realm flag so we can avoid legacy parsing. For messages, we use the onion but payload lengths 0 and 1 aren't special. Create a flag to disable that logic. Signed-off-by: Rusty Russell --- common/onion.c | 20 +++++++++++++------- common/onion.h | 2 ++ common/sphinx.c | 5 +++-- common/sphinx.h | 4 +++- devtools/onion.c | 4 ++-- lightningd/peer_htlcs.c | 2 +- wallet/test/run-wallet.c | 3 ++- 7 files changed, 26 insertions(+), 14 deletions(-) diff --git a/common/onion.c b/common/onion.c index 4b0f57cc777d..c74c9a1b26dc 100644 --- a/common/onion.c +++ b/common/onion.c @@ -143,6 +143,7 @@ u8 *onion_final_hop(const tal_t *ctx, /* Returns true if valid, and fills in type. */ static bool pull_payload_length(const u8 **cursor, size_t *max, + bool has_realm, enum onion_payload_type *type, size_t *len) { @@ -163,7 +164,7 @@ static bool pull_payload_length(const u8 **cursor, * length. In this case the `hop_payload_length` is defined to be 32 * bytes. */ - if (*len == 0) { + if (has_realm && *len == 0) { if (type) *type = ONION_V0_PAYLOAD; assert(*cursor - start == 1); @@ -176,10 +177,15 @@ static bool pull_payload_length(const u8 **cursor, * case the `hop_payload_length` is equal to the numeric value of * `length`. */ - if (*len > 1) { + if (!has_realm || *len > 1) { /* It's still invalid if it claims to be too long! */ - if (*len > ROUTING_INFO_SIZE - HMAC_SIZE) - return false; + if (has_realm) { + if (*len > ROUTING_INFO_SIZE - HMAC_SIZE) + return false; + } else { + if (*len > *max) + return false; + } if (type) *type = ONION_TLV_PAYLOAD; @@ -190,12 +196,12 @@ static bool pull_payload_length(const u8 **cursor, return false; } -size_t onion_payload_length(const u8 *raw_payload, size_t len, +size_t onion_payload_length(const u8 *raw_payload, size_t len, bool has_realm, bool *valid, enum onion_payload_type *type) { size_t max = len, payload_len; - *valid = pull_payload_length(&raw_payload, &max, type, &payload_len); + *valid = pull_payload_length(&raw_payload, &max, has_realm, type, &payload_len); /* If it's not valid, copy the entire thing. */ if (!*valid) @@ -214,7 +220,7 @@ struct onion_payload *onion_decode(const tal_t *ctx, size_t max = tal_bytelen(cursor), len; struct tlv_tlv_payload *tlv; - if (!pull_payload_length(&cursor, &max, &p->type, &len)) + if (!pull_payload_length(&cursor, &max, true, &p->type, &len)) return tal_free(p); switch (p->type) { diff --git a/common/onion.h b/common/onion.h index 1ec8d4eec4b1..7f7c38feb387 100644 --- a/common/onion.h +++ b/common/onion.h @@ -39,6 +39,7 @@ u8 *onion_final_hop(const tal_t *ctx, * onion_payload_length: measure payload length in decrypted onion. * @raw_payload: payload to look at. * @len: length of @raw_payload in bytes. + * @has_realm: used for HTLCs, where first byte 0 is magical. * @valid: set to true if it is valid, false otherwise. * @type: if non-NULL, set to type of payload if *@valid is true. * @@ -47,6 +48,7 @@ u8 *onion_final_hop(const tal_t *ctx, * the return value is @len (i.e. the entire payload). */ size_t onion_payload_length(const u8 *raw_payload, size_t len, + bool has_realm, bool *valid, enum onion_payload_type *type); diff --git a/common/sphinx.c b/common/sphinx.c index 53993c2aa552..2968fd067297 100644 --- a/common/sphinx.c +++ b/common/sphinx.c @@ -563,7 +563,8 @@ struct route_step *process_onionpacket( const struct onionpacket *msg, const struct secret *shared_secret, const u8 *assocdata, - const size_t assocdatalen + const size_t assocdatalen, + bool has_realm ) { struct route_step *step = talz(ctx, struct route_step); @@ -596,7 +597,7 @@ struct route_step *process_onionpacket( if (!blind_group_element(&step->next->ephemeralkey, &msg->ephemeralkey, blind)) return tal_free(step); - payload_size = onion_payload_length(paddedheader, ROUTING_INFO_SIZE, + payload_size = onion_payload_length(paddedheader, ROUTING_INFO_SIZE, has_realm, &valid, NULL); /* Can't decode? Treat it as terminal. */ diff --git a/common/sphinx.h b/common/sphinx.h index ccb57cd1b2d8..0c9ba9e7197d 100644 --- a/common/sphinx.h +++ b/common/sphinx.h @@ -133,13 +133,15 @@ bool onion_shared_secret( * @hoppayload: the per-hop payload destined for the processing node. * @assocdata: associated data to commit to in HMACs * @assocdatalen: length of the assocdata + * @has_realm: used for HTLCs, where first byte 0 is magical. */ struct route_step *process_onionpacket( const tal_t * ctx, const struct onionpacket *packet, const struct secret *shared_secret, const u8 *assocdata, - const size_t assocdatalen + const size_t assocdatalen, + bool has_realm ); /** diff --git a/devtools/onion.c b/devtools/onion.c index 5e0e75b61474..d3d0b1af5373 100644 --- a/devtools/onion.c +++ b/devtools/onion.c @@ -128,7 +128,7 @@ static struct route_step *decode_with_privkey(const tal_t *ctx, const u8 *onion, errx(1, "Error creating shared secret."); step = process_onionpacket(ctx, &packet, &shared_secret, assocdata, - tal_bytelen(assocdata)); + tal_bytelen(assocdata), true); return step; } @@ -282,7 +282,7 @@ static void runtest(const char *filename) errx(1, "Error serializing message."); onion_payload_length(step->raw_payload, tal_bytelen(step->raw_payload), - &valid, &type); + true, &valid, &type); assert(valid); printf(" Type: %d\n", type); printf(" Payload: %s\n", tal_hex(ctx, step->raw_payload)); diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index cfed09ca0248..a5a9994e0427 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -1108,7 +1108,7 @@ static bool peer_accepted_htlc(const tal_t *ctx, rs = process_onionpacket(tmpctx, &op, hin->shared_secret, hin->payment_hash.u.u8, - sizeof(hin->payment_hash)); + sizeof(hin->payment_hash), true); if (!rs) { *badonion = WIRE_INVALID_ONION_HMAC; log_debug(channel->log, diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index b555bc7e1747..bd185443c3d1 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -550,7 +550,8 @@ struct route_step *process_onionpacket( const struct onionpacket *packet UNNEEDED, const struct secret *shared_secret UNNEEDED, const u8 *assocdata UNNEEDED, - const size_t assocdatalen + const size_t assocdatalen UNNEEDED, + bool has_realm ) { fprintf(stderr, "process_onionpacket called!\n"); abort(); } /* Generated stub for serialize_onionpacket */