mirror of
https://github.com/aljazceru/lightning.git
synced 2026-02-06 22:54:21 +01:00
common/onion: EXPERIMENTAL handling of enctlv field to override next_short_channel_id.
This requires us to call ecdh() in the corner case where the blinding seed is in the TLV itself (which is the case for the start of a blinded route). Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
#include "common/onion.h"
|
||||
#include <assert.h>
|
||||
#include <ccan/array_size/array_size.h>
|
||||
#include <common/ecdh.h>
|
||||
#include <common/sphinx.h>
|
||||
#include <sodium/crypto_aead_chacha20poly1305.h>
|
||||
#include <wire/gen_onion_wire.h>
|
||||
|
||||
/* BOLT #4:
|
||||
@@ -210,8 +212,50 @@ size_t onion_payload_length(const u8 *raw_payload, size_t len, bool has_realm,
|
||||
return payload_len;
|
||||
}
|
||||
|
||||
#if EXPERIMENTAL_FEATURES
|
||||
static struct tlv_tlv_payload *decrypt_tlv(const tal_t *ctx,
|
||||
const struct secret *blinding_ss,
|
||||
const u8 *enc)
|
||||
{
|
||||
const unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
struct secret rho;
|
||||
u8 *dec;
|
||||
const u8 *cursor;
|
||||
size_t max;
|
||||
int ret;
|
||||
struct tlv_tlv_payload *tlv;
|
||||
|
||||
subkey_from_hmac("rho", blinding_ss, &rho);
|
||||
if (tal_bytelen(enc) < crypto_aead_chacha20poly1305_ietf_ABYTES)
|
||||
return NULL;
|
||||
|
||||
dec = tal_arr(tmpctx, u8,
|
||||
tal_bytelen(enc)
|
||||
- crypto_aead_chacha20poly1305_ietf_ABYTES);
|
||||
ret = crypto_aead_chacha20poly1305_ietf_decrypt(dec, NULL,
|
||||
NULL,
|
||||
enc,
|
||||
tal_bytelen(enc),
|
||||
NULL, 0,
|
||||
npub,
|
||||
rho.data);
|
||||
if (ret != 0)
|
||||
return NULL;
|
||||
|
||||
tlv = tlv_tlv_payload_new(ctx);
|
||||
cursor = dec;
|
||||
max = tal_bytelen(dec);
|
||||
if (!fromwire_tlv_payload(&cursor, &max, tlv))
|
||||
return tal_free(tlv);
|
||||
|
||||
return tlv;
|
||||
}
|
||||
#endif /* EXPERIMENTAL_FEATURES */
|
||||
|
||||
struct onion_payload *onion_decode(const tal_t *ctx,
|
||||
const struct route_step *rs,
|
||||
const struct pubkey *blinding,
|
||||
const struct secret *blinding_ss,
|
||||
u64 *failtlvtype,
|
||||
size_t *failtlvpos)
|
||||
{
|
||||
@@ -231,6 +275,10 @@ struct onion_payload *onion_decode(const tal_t *ctx,
|
||||
p->amt_to_forward = fromwire_amount_msat(&cursor, &max);
|
||||
p->outgoing_cltv = fromwire_u32(&cursor, &max);
|
||||
p->payment_secret = NULL;
|
||||
p->blinding = NULL;
|
||||
/* We can't handle blinding with a legacy payload */
|
||||
if (blinding)
|
||||
return tal_free(p);
|
||||
|
||||
if (rs->nextcase == ONION_FORWARD) {
|
||||
p->total_msat = NULL;
|
||||
@@ -296,6 +344,47 @@ struct onion_payload *onion_decode(const tal_t *ctx,
|
||||
}
|
||||
|
||||
p->payment_secret = NULL;
|
||||
if (blinding)
|
||||
p->blinding = tal_dup(p, struct pubkey, blinding);
|
||||
else
|
||||
p->blinding = NULL;
|
||||
|
||||
#if EXPERIMENTAL_FEATURES
|
||||
if (!p->blinding) {
|
||||
/* If we have no blinding, it could be in TLV. */
|
||||
if (tlv->blinding_seed) {
|
||||
p->blinding =
|
||||
tal_dup(p, struct pubkey,
|
||||
&tlv->blinding_seed->blinding_seed);
|
||||
ecdh(p->blinding, &p->blinding_ss);
|
||||
}
|
||||
} else
|
||||
p->blinding_ss = *blinding_ss;
|
||||
|
||||
if (p->blinding) {
|
||||
/* If they give us a blinding and we're not terminal,
|
||||
* we must have an enctlv. */
|
||||
if (rs->nextcase == ONION_FORWARD) {
|
||||
struct tlv_tlv_payload *ntlv;
|
||||
|
||||
if (!tlv->enctlv)
|
||||
goto fail;
|
||||
|
||||
ntlv = decrypt_tlv(tmpctx,
|
||||
&p->blinding_ss,
|
||||
tlv->enctlv->enctlv);
|
||||
if (!ntlv)
|
||||
goto fail;
|
||||
|
||||
/* Must override short_channel_id */
|
||||
if (!ntlv->short_channel_id)
|
||||
goto fail;
|
||||
|
||||
*p->forward_channel
|
||||
= ntlv->short_channel_id->short_channel_id;
|
||||
}
|
||||
}
|
||||
#endif /* EXPERIMENTAL_FEATURES */
|
||||
|
||||
if (tlv->payment_data) {
|
||||
p->payment_secret = tal_dup(p, struct secret,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef LIGHTNING_COMMON_ONION_H
|
||||
#define LIGHTNING_COMMON_ONION_H
|
||||
#include "config.h"
|
||||
#include <bitcoin/privkey.h>
|
||||
#include <ccan/short_types/short_types.h>
|
||||
#include <common/amount.h>
|
||||
|
||||
@@ -19,6 +20,10 @@ struct onion_payload {
|
||||
struct amount_msat *total_msat;
|
||||
struct short_channel_id *forward_channel;
|
||||
struct secret *payment_secret;
|
||||
|
||||
/* If blinding is set, blinding_ss is the shared secret.*/
|
||||
struct pubkey *blinding;
|
||||
struct secret blinding_ss;
|
||||
};
|
||||
|
||||
u8 *onion_nonfinal_hop(const tal_t *ctx,
|
||||
@@ -57,11 +62,17 @@ size_t onion_payload_length(const u8 *raw_payload, size_t len,
|
||||
* @ctx: context to allocate onion_contents off.
|
||||
* @rs: the route_step, whose raw_payload is of at least length
|
||||
* onion_payload_length().
|
||||
* @blinding: the optional incoming blinding point.
|
||||
* @blinding_ss: the shared secret derived from @blinding (iff that's non-NULL)
|
||||
* @failtlvtype: (out) the tlv type which failed to parse.
|
||||
* @failtlvpos: (out) the offset in the tlv which failed to parse.
|
||||
*
|
||||
* If the payload is not valid, returns NULL.
|
||||
*/
|
||||
struct onion_payload *onion_decode(const tal_t *ctx,
|
||||
const struct route_step *rs,
|
||||
const struct pubkey *blinding,
|
||||
const struct secret *blinding_ss,
|
||||
u64 *failtlvtype,
|
||||
size_t *failtlvpos);
|
||||
|
||||
|
||||
@@ -1118,6 +1118,7 @@ static bool peer_accepted_htlc(const tal_t *ctx,
|
||||
|
||||
hook_payload->route_step = tal_steal(hook_payload, rs);
|
||||
hook_payload->payload = onion_decode(hook_payload, rs,
|
||||
NULL, NULL,
|
||||
&hook_payload->failtlvtype,
|
||||
&hook_payload->failtlvpos);
|
||||
hook_payload->ld = ld;
|
||||
|
||||
@@ -412,6 +412,8 @@ enum watch_result onchaind_funding_spent(struct channel *channel UNNEEDED,
|
||||
/* Generated stub for onion_decode */
|
||||
struct onion_payload *onion_decode(const tal_t *ctx UNNEEDED,
|
||||
const struct route_step *rs UNNEEDED,
|
||||
const struct pubkey *blinding UNNEEDED,
|
||||
const struct secret *blinding_ss UNNEEDED,
|
||||
u64 *failtlvtype UNNEEDED,
|
||||
size_t *failtlvpos UNNEEDED)
|
||||
{ fprintf(stderr, "onion_decode called!\n"); abort(); }
|
||||
|
||||
Reference in New Issue
Block a user