mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
sphinx: Using hop_data to serialize per-hop information into onion
Signed-off-by: Christian Decker <decker.christian@gmail.com>
This commit is contained in:
parent
752f884c23
commit
83e89f0fe5
@ -330,9 +330,35 @@ static struct hop_params *generate_hop_params(
|
|||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void serialize_hop_data(tal_t *ctx, u8 *dst, const struct hop_data *data)
|
||||||
|
{
|
||||||
|
u8 *buf = tal_arr(ctx, u8, 0);
|
||||||
|
towire_u8(&buf, data->realm);
|
||||||
|
towire_short_channel_id(&buf, &data->channel_id);
|
||||||
|
towire_u32(&buf, data->amt_forward);
|
||||||
|
towire_u32(&buf, data->outgoing_cltv);
|
||||||
|
towire_pad(&buf, 16);
|
||||||
|
towire(&buf, data->hmac, SECURITY_PARAMETER);
|
||||||
|
memcpy(dst, buf, tal_len(buf));
|
||||||
|
tal_free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void deserialize_hop_data(struct hop_data *data, const u8 *src)
|
||||||
|
{
|
||||||
|
const u8 *cursor = src;
|
||||||
|
size_t max = HOP_DATA_SIZE;
|
||||||
|
data->realm = fromwire_u8(&cursor, &max);
|
||||||
|
fromwire_short_channel_id(&cursor, &max, &data->channel_id);
|
||||||
|
data->amt_forward = fromwire_u32(&cursor, &max);
|
||||||
|
data->outgoing_cltv = fromwire_u32(&cursor, &max);
|
||||||
|
fromwire_pad(&cursor, &max, 16);
|
||||||
|
fromwire(&cursor, &max, &data->hmac, SECURITY_PARAMETER);
|
||||||
|
}
|
||||||
|
|
||||||
struct onionpacket *create_onionpacket(
|
struct onionpacket *create_onionpacket(
|
||||||
const tal_t *ctx,
|
const tal_t *ctx,
|
||||||
struct pubkey *path,
|
struct pubkey *path,
|
||||||
|
struct hop_data hops_data[],
|
||||||
const u8 *sessionkey,
|
const u8 *sessionkey,
|
||||||
const u8 *assocdata,
|
const u8 *assocdata,
|
||||||
const size_t assocdatalen
|
const size_t assocdatalen
|
||||||
@ -340,7 +366,7 @@ struct onionpacket *create_onionpacket(
|
|||||||
{
|
{
|
||||||
struct onionpacket *packet = talz(ctx, struct onionpacket);
|
struct onionpacket *packet = talz(ctx, struct onionpacket);
|
||||||
int i, num_hops = tal_count(path);
|
int i, num_hops = tal_count(path);
|
||||||
u8 filler[2 * (num_hops - 1) * SECURITY_PARAMETER];
|
u8 filler[(num_hops - 1) * HOP_DATA_SIZE];
|
||||||
struct keyset keys;
|
struct keyset keys;
|
||||||
u8 nextaddr[20], nexthmac[SECURITY_PARAMETER];
|
u8 nextaddr[20], nexthmac[SECURITY_PARAMETER];
|
||||||
u8 stream[ROUTING_INFO_SIZE];
|
u8 stream[ROUTING_INFO_SIZE];
|
||||||
@ -353,22 +379,22 @@ struct onionpacket *create_onionpacket(
|
|||||||
memset(nexthmac, 0, 20);
|
memset(nexthmac, 0, 20);
|
||||||
memset(packet->routinginfo, 0, ROUTING_INFO_SIZE);
|
memset(packet->routinginfo, 0, ROUTING_INFO_SIZE);
|
||||||
|
|
||||||
generate_header_padding(filler, sizeof(filler), 2 * SECURITY_PARAMETER,
|
generate_header_padding(filler, sizeof(filler), HOP_DATA_SIZE,
|
||||||
"rho", 3, num_hops, params);
|
"rho", 3, num_hops, params);
|
||||||
|
|
||||||
for (i = num_hops - 1; i >= 0; i--) {
|
for (i = num_hops - 1; i >= 0; i--) {
|
||||||
|
memcpy(hops_data[i].hmac, nexthmac, SECURITY_PARAMETER);
|
||||||
generate_key_set(params[i].secret, &keys);
|
generate_key_set(params[i].secret, &keys);
|
||||||
generate_cipher_stream(stream, keys.rho, ROUTING_INFO_SIZE);
|
generate_cipher_stream(stream, keys.rho, ROUTING_INFO_SIZE);
|
||||||
|
|
||||||
/* Rightshift mix-header by 2*SECURITY_PARAMETER */
|
/* Rightshift mix-header by 2*SECURITY_PARAMETER */
|
||||||
memmove(packet->routinginfo + 2 * SECURITY_PARAMETER, packet->routinginfo,
|
memmove(packet->routinginfo + HOP_DATA_SIZE, packet->routinginfo,
|
||||||
ROUTING_INFO_SIZE - 2 * SECURITY_PARAMETER);
|
ROUTING_INFO_SIZE - HOP_DATA_SIZE);
|
||||||
memcpy(packet->routinginfo, nextaddr, SECURITY_PARAMETER);
|
serialize_hop_data(packet, packet->routinginfo, &hops_data[i]);
|
||||||
memcpy(packet->routinginfo + SECURITY_PARAMETER, nexthmac, SECURITY_PARAMETER);
|
|
||||||
xorbytes(packet->routinginfo, packet->routinginfo, stream, ROUTING_INFO_SIZE);
|
xorbytes(packet->routinginfo, packet->routinginfo, stream, ROUTING_INFO_SIZE);
|
||||||
|
|
||||||
if (i == num_hops - 1) {
|
if (i == num_hops - 1) {
|
||||||
size_t len = (NUM_MAX_HOPS - num_hops + 1) * 2 * SECURITY_PARAMETER;
|
size_t len = (NUM_MAX_HOPS - num_hops + 1) * HOP_DATA_SIZE;
|
||||||
memcpy(packet->routinginfo + len, filler, sizeof(filler));
|
memcpy(packet->routinginfo + len, filler, sizeof(filler));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,7 +424,7 @@ struct route_step *process_onionpacket(
|
|||||||
struct keyset keys;
|
struct keyset keys;
|
||||||
u8 blind[BLINDING_FACTOR_SIZE];
|
u8 blind[BLINDING_FACTOR_SIZE];
|
||||||
u8 stream[NUM_STREAM_BYTES];
|
u8 stream[NUM_STREAM_BYTES];
|
||||||
u8 paddedheader[ROUTING_INFO_SIZE + 2 * SECURITY_PARAMETER];
|
u8 paddedheader[ROUTING_INFO_SIZE + HOP_DATA_SIZE];
|
||||||
|
|
||||||
step->next = talz(step, struct onionpacket);
|
step->next = talz(step, struct onionpacket);
|
||||||
step->next->version = msg->version;
|
step->next->version = msg->version;
|
||||||
@ -421,12 +447,12 @@ struct route_step *process_onionpacket(
|
|||||||
compute_blinding_factor(&msg->ephemeralkey, shared_secret, blind);
|
compute_blinding_factor(&msg->ephemeralkey, shared_secret, blind);
|
||||||
if (!blind_group_element(&step->next->ephemeralkey, &msg->ephemeralkey, blind))
|
if (!blind_group_element(&step->next->ephemeralkey, &msg->ephemeralkey, blind))
|
||||||
return tal_free(step);
|
return tal_free(step);
|
||||||
memcpy(&step->next->nexthop, paddedheader, SECURITY_PARAMETER);
|
|
||||||
memcpy(&step->next->mac,
|
|
||||||
paddedheader + SECURITY_PARAMETER,
|
|
||||||
SECURITY_PARAMETER);
|
|
||||||
|
|
||||||
memcpy(&step->next->routinginfo, paddedheader + 2 * SECURITY_PARAMETER, ROUTING_INFO_SIZE);
|
deserialize_hop_data(&step->hop_data, paddedheader);
|
||||||
|
|
||||||
|
memcpy(&step->next->mac, step->hop_data.hmac, SECURITY_PARAMETER);
|
||||||
|
|
||||||
|
memcpy(&step->next->routinginfo, paddedheader + HOP_DATA_SIZE, ROUTING_INFO_SIZE);
|
||||||
|
|
||||||
if (memeqzero(step->next->mac, sizeof(step->next->mac))) {
|
if (memeqzero(step->next->mac, sizeof(step->next->mac))) {
|
||||||
step->nextcase = ONION_END;
|
step->nextcase = ONION_END;
|
||||||
|
@ -9,11 +9,12 @@
|
|||||||
#include <ccan/tal/tal.h>
|
#include <ccan/tal/tal.h>
|
||||||
#include <secp256k1.h>
|
#include <secp256k1.h>
|
||||||
#include <sodium/randombytes.h>
|
#include <sodium/randombytes.h>
|
||||||
|
#include <wire/wire.h>
|
||||||
|
|
||||||
#define SECURITY_PARAMETER 20
|
#define SECURITY_PARAMETER 20
|
||||||
#define NUM_MAX_HOPS 20
|
#define NUM_MAX_HOPS 20
|
||||||
#define HOP_DATA_SIZE 40
|
#define HOP_DATA_SIZE 53
|
||||||
#define ROUTING_INFO_SIZE (HOP_DATA_SIZE * SECURITY_PARAMETER)
|
#define ROUTING_INFO_SIZE (HOP_DATA_SIZE * NUM_MAX_HOPS)
|
||||||
#define TOTAL_PACKET_SIZE (1 + 33 + SECURITY_PARAMETER + ROUTING_INFO_SIZE)
|
#define TOTAL_PACKET_SIZE (1 + 33 + SECURITY_PARAMETER + ROUTING_INFO_SIZE)
|
||||||
|
|
||||||
struct onionpacket {
|
struct onionpacket {
|
||||||
@ -34,23 +35,35 @@ enum route_next_case {
|
|||||||
|
|
||||||
/* BOLT #4:
|
/* BOLT #4:
|
||||||
*
|
*
|
||||||
* The format of the per-hop-payload for a version 0 packet is as follows:
|
* The hops_data field is a structure that holds obfuscated versions of the next hop's address, transfer information and the associated HMAC. It is 1060 bytes long, and has the following structure:
|
||||||
|
|
||||||
```
|
```
|
||||||
+----------------+--------------------------+-------------------------------+--------------------------------------------+
|
+-----------+-------------+----------+-----------+-------------+----------+-----------+
|
||||||
| realm (1 byte) | amt_to_forward (8 bytes) | outgoing_cltv_value (4 bytes) | unused_with_v0_version_on_header (7 bytes) |
|
| n_1 realm | n_1 per-hop | n_1 HMAC | n_2 realm | n_2 per-hop | n_2 HMAC | ...filler |
|
||||||
+----------------+--------------------------+-------------------------------+--------------------------------------------+
|
+-----------+-------------+----------+----------+--------------+----------+------------+
|
||||||
|
```
|
||||||
|
|
||||||
|
The realm byte determines the format of the per-hop; so far only realm 0 is defined, and for that, the per-hop format is:
|
||||||
|
|
||||||
|
```
|
||||||
|
+----------------------+--------------------------+-------------------------------+--------------------+
|
||||||
|
| channel_id (8 bytes) | amt_to_forward (4 bytes) | outgoing_cltv_value (4 bytes) | padding (16 bytes) |
|
||||||
|
+----------------------+--------------------------+-------------------------------+--------------------+
|
||||||
```
|
```
|
||||||
*/
|
*/
|
||||||
struct hoppayload {
|
struct hop_data {
|
||||||
u8 realm;
|
u8 realm;
|
||||||
u64 amt_to_forward;
|
struct short_channel_id channel_id;
|
||||||
u32 outgoing_cltv_value;
|
u32 amt_forward;
|
||||||
u8 unused_with_v0_version_on_header[7];
|
u32 outgoing_cltv;
|
||||||
|
/* Padding omitted, will be zeroed */
|
||||||
|
u8 hmac[SECURITY_PARAMETER];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct route_step {
|
struct route_step {
|
||||||
enum route_next_case nextcase;
|
enum route_next_case nextcase;
|
||||||
struct onionpacket *next;
|
struct onionpacket *next;
|
||||||
|
struct hop_data hop_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -69,6 +82,7 @@ struct route_step {
|
|||||||
struct onionpacket *create_onionpacket(
|
struct onionpacket *create_onionpacket(
|
||||||
const tal_t * ctx,
|
const tal_t * ctx,
|
||||||
struct pubkey path[],
|
struct pubkey path[],
|
||||||
|
struct hop_data hops_data[],
|
||||||
const u8 * sessionkey,
|
const u8 * sessionkey,
|
||||||
const u8 *assocdata,
|
const u8 *assocdata,
|
||||||
const size_t assocdatalen
|
const size_t assocdatalen
|
||||||
|
@ -131,6 +131,7 @@ int main(int argc, char **argv)
|
|||||||
struct pubkey *path = tal_arr(ctx, struct pubkey, num_hops);
|
struct pubkey *path = tal_arr(ctx, struct pubkey, num_hops);
|
||||||
u8 privkeys[argc - 1][32];
|
u8 privkeys[argc - 1][32];
|
||||||
u8 sessionkey[32];
|
u8 sessionkey[32];
|
||||||
|
struct hop_data hops_data[num_hops];
|
||||||
|
|
||||||
memset(&sessionkey, 'A', sizeof(sessionkey));
|
memset(&sessionkey, 'A', sizeof(sessionkey));
|
||||||
|
|
||||||
@ -141,9 +142,13 @@ int main(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i=0; i<num_hops; i++) {
|
||||||
|
memset(&hops_data[i], 'A', sizeof(hops_data[i]));
|
||||||
|
}
|
||||||
|
|
||||||
struct onionpacket *res = create_onionpacket(ctx,
|
struct onionpacket *res = create_onionpacket(ctx,
|
||||||
path,
|
path,
|
||||||
|
hops_data,
|
||||||
sessionkey,
|
sessionkey,
|
||||||
assocdata,
|
assocdata,
|
||||||
sizeof(assocdata));
|
sizeof(assocdata));
|
||||||
|
Loading…
Reference in New Issue
Block a user