Skip to content

Commit

Permalink
spec: import latest onionmessage spec, based on routeblinding.
Browse files Browse the repository at this point in the history
This is from 6e99c5feaf60cb797507d181fe583224309318e9

We renamed the enctlv field to encrypted_recipient_data in the spec, and the
new onion_message is message 513.  We don't handle it until the next patch.

Two renames:
1. blinding_seed -> blinding_point.
2. enctlv -> encrypted_recipient_data.

We don't do a compat cycle for our JSON APIs for these experimental
features only used by our own plugins, we just rename.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
  • Loading branch information
rustyrussell committed Nov 30, 2021
1 parent 1ec6346 commit b3af5f5
Show file tree
Hide file tree
Showing 22 changed files with 386 additions and 81 deletions.
1 change: 1 addition & 0 deletions channeld/channeld.c
Original file line number Diff line number Diff line change
Expand Up @@ -2321,6 +2321,7 @@ static void peer_in(struct peer *peer, const u8 *msg)
case WIRE_WARNING:
case WIRE_ERROR:
case WIRE_OBS2_ONION_MESSAGE:
case WIRE_ONION_MESSAGE:
abort();
}

Expand Down
232 changes: 206 additions & 26 deletions common/blindedpath.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ static bool blind_node(const struct privkey *blinding,
return true;
}

static u8 *enctlv_from_encmsg(const tal_t *ctx,
const struct privkey *blinding,
const struct pubkey *node,
const struct tlv_obs2_encmsg_tlvs *encmsg,
struct privkey *next_blinding,
struct pubkey *node_alias)
static u8 *enctlv_from_encmsg_raw(const tal_t *ctx,
const struct privkey *blinding,
const struct pubkey *node,
const u8 *raw_encmsg TAKES,
struct privkey *next_blinding,
struct pubkey *node_alias)
{
/* https://github.com/lightningnetwork/lightning-rfc/blob/route-blinding/proposals/route-blinding.md */
struct secret ss, rho;
Expand All @@ -87,9 +87,7 @@ static u8 *enctlv_from_encmsg(const tal_t *ctx,
if (!blind_node(blinding, &ss, node, node_alias, next_blinding))
return NULL;

/* Marshall */
ret = tal_arr(ctx, u8, 0);
towire_obs2_encmsg_tlvs(&ret, encmsg);
ret = tal_dup_talarr(ctx, u8, raw_encmsg);
SUPERVERBOSE("\t\"encmsg_hex\": \"%s\",\n", tal_hex(tmpctx, ret));

/*
Expand All @@ -115,6 +113,32 @@ static u8 *enctlv_from_encmsg(const tal_t *ctx,
return ret;
}

static u8 *enctlv_from_obs2_encmsg(const tal_t *ctx,
const struct privkey *blinding,
const struct pubkey *node,
const struct tlv_obs2_encmsg_tlvs *encmsg,
struct privkey *next_blinding,
struct pubkey *node_alias)
{
u8 *encmsg_raw = tal_arr(NULL, u8, 0);
towire_obs2_encmsg_tlvs(&encmsg_raw, encmsg);
return enctlv_from_encmsg_raw(ctx, blinding, node, take(encmsg_raw),
next_blinding, node_alias);
}

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 *encmsg_raw = tal_arr(NULL, u8, 0);
towire_encrypted_data_tlv(&encmsg_raw, encmsg);
return enctlv_from_encmsg_raw(ctx, blinding, node, take(encmsg_raw),
next_blinding, node_alias);
}

bool unblind_onion(const struct pubkey *blinding,
void (*ecdh)(const struct pubkey *point, struct secret *ss),
struct pubkey *onion_key,
Expand All @@ -136,16 +160,13 @@ bool unblind_onion(const struct pubkey *blinding,
hmac.data) == 1;
}

static struct tlv_obs2_encmsg_tlvs *decrypt_encmsg(const tal_t *ctx,
const struct pubkey *blinding,
const struct secret *ss,
const u8 *enctlv)
static u8 *decrypt_encmsg_raw(const tal_t *ctx,
const struct pubkey *blinding,
const struct secret *ss,
const u8 *enctlv)
{
struct secret rho;
u8 *dec;
const u8 *cursor;
size_t maxlen;
struct tlv_obs2_encmsg_tlvs *encmsg;
/* All-zero npub */
static const unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES];

Expand All @@ -161,18 +182,27 @@ static struct tlv_obs2_encmsg_tlvs *decrypt_encmsg(const tal_t *ctx,
if (tal_bytelen(enctlv) < crypto_aead_chacha20poly1305_ietf_ABYTES)
return NULL;

dec = tal_arr(tmpctx, u8, tal_bytelen(enctlv)
dec = tal_arr(ctx, u8, tal_bytelen(enctlv)
- crypto_aead_chacha20poly1305_ietf_ABYTES);
if (crypto_aead_chacha20poly1305_ietf_decrypt(dec, NULL,
NULL,
enctlv, tal_bytelen(enctlv),
NULL, 0,
npub,
rho.data) != 0)
return NULL;
return tal_free(dec);

return dec;
}

cursor = dec;
maxlen = tal_bytelen(dec);
static struct tlv_obs2_encmsg_tlvs *decrypt_obs2_encmsg(const tal_t *ctx,
const struct pubkey *blinding,
const struct secret *ss,
const u8 *enctlv)
{
struct tlv_obs2_encmsg_tlvs *encmsg;
const u8 *cursor = decrypt_encmsg_raw(tmpctx, blinding, ss, enctlv);
size_t maxlen = tal_bytelen(cursor);

/* BOLT-onion-message #4:
*
Expand All @@ -187,6 +217,156 @@ static struct tlv_obs2_encmsg_tlvs *decrypt_encmsg(const tal_t *ctx,
return encmsg;
}

static struct tlv_encrypted_data_tlv *decrypt_encmsg(const tal_t *ctx,
const struct pubkey *blinding,
const struct secret *ss,
const u8 *enctlv)
{
struct tlv_encrypted_data_tlv *encmsg;
const u8 *cursor = decrypt_encmsg_raw(tmpctx, blinding, ss, enctlv);
size_t maxlen = tal_bytelen(cursor);

/* BOLT-onion-message #4:
*
* - if the `enctlv` is not a valid TLV...
* - MUST drop the message.
*/
encmsg = tlv_encrypted_data_tlv_new(ctx);
if (!fromwire_encrypted_data_tlv(&cursor, &maxlen, encmsg)
|| !tlv_fields_valid(encmsg->fields, NULL, NULL))
return tal_free(encmsg);

return encmsg;
}

bool decrypt_enctlv(const struct pubkey *blinding,
const struct secret *ss,
const u8 *enctlv,
struct pubkey *next_node,
struct pubkey *next_blinding)
{
struct tlv_encrypted_data_tlv *encmsg;

encmsg = decrypt_encmsg(tmpctx, blinding, ss, enctlv);
if (!encmsg)
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 (!encmsg->next_node_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.
*/
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 `blinding` is specified in the `enctlv`:
* - MUST pass that as `blinding` in the `onion_message`
* - otherwise:
* - MUST pass `blinding` derived as in
* [Route Blinding][route-blinding] (i.e.
* `E(i+1) = H(E(i) || ss(i)) * E(i)`).
*/
*next_node = *encmsg->next_node_id;
if (encmsg->next_blinding_override)
*next_blinding = *encmsg->next_blinding_override;
else {
/* E(i-1) = H(E(i) || ss(i)) * E(i) */
struct sha256 h;
blinding_hash_e_and_ss(blinding, ss, &h);
blinding_next_pubkey(blinding, &h, next_blinding);
}
return true;
}

bool decrypt_final_enctlv(const tal_t *ctx,
const struct pubkey *blinding,
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;
struct secret node_id_blinding;

/* Repeat the tweak to get the alias it was using for us */
subkey_from_hmac("blinded_node_id", ss, &node_id_blinding);
*alias = *my_id;
if (secp256k1_ec_pubkey_tweak_mul(secp256k1_ctx,
&alias->pubkey,
node_id_blinding.data) != 1)
return false;

encmsg = decrypt_encmsg(tmpctx, blinding, ss, enctlv);
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;
}

u8 *create_enctlv(const tal_t *ctx,
const struct privkey *blinding,
const struct pubkey *node,
const struct pubkey *next_node,
size_t padlen,
const struct pubkey *next_blinding_override,
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);

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,
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);

return enctlv_from_encmsg(ctx, blinding, final_node, encmsg,
&unused_next_blinding, node_alias);
}

/* Obsolete variants */
bool decrypt_obs2_enctlv(const struct pubkey *blinding,
const struct secret *ss,
const u8 *enctlv,
Expand All @@ -195,7 +375,7 @@ bool decrypt_obs2_enctlv(const struct pubkey *blinding,
{
struct tlv_obs2_encmsg_tlvs *encmsg;

encmsg = decrypt_encmsg(tmpctx, blinding, ss, enctlv);
encmsg = decrypt_obs2_encmsg(tmpctx, blinding, ss, enctlv);
if (!encmsg)
return false;

Expand Down Expand Up @@ -263,7 +443,7 @@ bool decrypt_obs2_final_enctlv(const tal_t *ctx,
node_id_blinding.data) != 1)
return false;

encmsg = decrypt_encmsg(tmpctx, blinding, ss, enctlv);
encmsg = decrypt_obs2_encmsg(tmpctx, blinding, ss, enctlv);
if (!encmsg)
return false;

Expand Down Expand Up @@ -291,8 +471,8 @@ u8 *create_obs2_enctlv(const tal_t *ctx,
encmsg->next_node_id = cast_const(struct pubkey *, next_node);
encmsg->next_blinding = cast_const(struct pubkey *, override_blinding);

return enctlv_from_encmsg(ctx, blinding, node, encmsg,
next_blinding, node_alias);
return enctlv_from_obs2_encmsg(ctx, blinding, node, encmsg,
next_blinding, node_alias);
}

u8 *create_obs2_final_enctlv(const tal_t *ctx,
Expand All @@ -310,6 +490,6 @@ u8 *create_obs2_final_enctlv(const tal_t *ctx,
if (self_id)
encmsg->self_id = (u8 *)tal_dup(encmsg, struct secret, self_id);

return enctlv_from_encmsg(ctx, blinding, final_node, encmsg,
&unused_next_blinding, node_alias);
return enctlv_from_obs2_encmsg(ctx, blinding, final_node, encmsg,
&unused_next_blinding, node_alias);
}
Loading

0 comments on commit b3af5f5

Please sign in to comment.