sphinx: Variable left-shift when unwrapping onion

This is all it takes on the read side to use multiple frames. We are
overshooting the padding a bit since we can at most use 16 additional frames,
but ChaCha20 is cheap.

Signed-off-by: Christian Decker <decker.christian@gmail.com>
This commit is contained in:
Christian Decker 2019-02-20 14:27:37 +01:00 committed by Rusty Russell
parent 7bc4cf83b1
commit d607afd195
2 changed files with 63 additions and 8 deletions

View file

@ -436,8 +436,6 @@ static void deserialize_hop_data(struct hop_data *data, const u8 *src)
fromwire_short_channel_id(&cursor, &max, &data->channel_id); fromwire_short_channel_id(&cursor, &max, &data->channel_id);
data->amt_forward = fromwire_amount_msat(&cursor, &max); data->amt_forward = fromwire_amount_msat(&cursor, &max);
data->outgoing_cltv = fromwire_u32(&cursor, &max); data->outgoing_cltv = fromwire_u32(&cursor, &max);
fromwire_pad(&cursor, &max, 12);
fromwire(&cursor, &max, &data->hmac, HMAC_SIZE);
} }
static void sphinx_write_frame(u8 *dest, const struct sphinx_hop *hop) static void sphinx_write_frame(u8 *dest, const struct sphinx_hop *hop)
@ -457,6 +455,35 @@ static void sphinx_write_frame(u8 *dest, const struct sphinx_hop *hop)
memcpy(dest + hop_size - HMAC_SIZE, hop->hmac, HMAC_SIZE); memcpy(dest + hop_size - HMAC_SIZE, hop->hmac, HMAC_SIZE);
} }
static void sphinx_parse_payload(struct route_step *step, const u8 *src)
{
size_t hop_size, raw_size, vsize;
/* Legacy hop_data support */
if (src[0] == 0x00) {
vsize = 1;
raw_size = 32;
hop_size = FRAME_SIZE;
step->realm = src[0];
} else {
vsize = varint_get(src, 3, &raw_size);
hop_size = raw_size + vsize + HMAC_SIZE;
}
/* Copy common pieces over */
step->raw_payload = tal_dup_arr(step, u8, src + vsize, raw_size, 0);
memcpy(step->next->mac, src + hop_size - HMAC_SIZE, HMAC_SIZE);
/* And now try to parse whatever the payload contains so we can use it
* later. */
if (step->realm == SPHINX_V0_PAYLOAD) {
step->type = SPHINX_V0_PAYLOAD;
deserialize_hop_data(&step->payload.v0, src);
} else {
step->type = SPHINX_RAW_PAYLOAD;
}
}
struct onionpacket *create_onionpacket( struct onionpacket *create_onionpacket(
const tal_t *ctx, const tal_t *ctx,
struct sphinx_path *sp, struct sphinx_path *sp,
@ -539,7 +566,8 @@ 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 + FRAME_SIZE]; u8 paddedheader[2*ROUTING_INFO_SIZE];
size_t shift_size, vsize;
step->next = talz(step, struct onionpacket); step->next = talz(step, struct onionpacket);
step->next->version = msg->version; step->next->version = msg->version;
@ -564,12 +592,30 @@ struct route_step *process_onionpacket(
return tal_free(step); return tal_free(step);
deserialize_hop_data(&step->hop_data, paddedheader); deserialize_hop_data(&step->hop_data, paddedheader);
sphinx_parse_payload(step, paddedheader);
/* Extract how many bytes we need to shift away */
if (paddedheader[0] == 0x00) {
shift_size = FRAME_SIZE;
} else {
/* In addition to the raw payload we need to also shift the
* length encoding itself and the HMAC away. */
vsize = varint_get(paddedheader, 3, &shift_size);
shift_size += vsize + HMAC_SIZE;
/* If we get an unreasonable shift size we must return an error. */
if (shift_size >= ROUTING_INFO_SIZE)
return tal_free(step);
}
memcpy(&step->next->mac, step->hop_data.hmac, HMAC_SIZE);
step->raw_payload = tal_dup_arr(step, u8, paddedheader + 1, step->raw_payload = tal_dup_arr(step, u8, paddedheader + 1,
FRAME_SIZE - 1 - HMAC_SIZE, 0); shift_size - 1 - HMAC_SIZE, 0);
memcpy(&step->next->routinginfo, paddedheader + FRAME_SIZE, ROUTING_INFO_SIZE); /* Copy the hmac from the last HMAC_SIZE bytes */
memcpy(&step->next->mac, paddedheader + shift_size - HMAC_SIZE, HMAC_SIZE);
/* Left shift the current payload out and make the remainder the new onion */
memcpy(&step->next->routinginfo, paddedheader + shift_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;

View file

@ -83,15 +83,24 @@ struct hop_data {
struct short_channel_id channel_id; struct short_channel_id channel_id;
struct amount_msat amt_forward; struct amount_msat amt_forward;
u32 outgoing_cltv; u32 outgoing_cltv;
/* Padding omitted, will be zeroed */ };
u8 hmac[HMAC_SIZE];
enum sphinx_payload_type {
SPHINX_V0_PAYLOAD = 0,
SPHINX_RAW_PAYLOAD = 255,
}; };
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; struct hop_data hop_data;
u8 realm;
enum sphinx_payload_type type;
union {
struct hop_data v0;
} payload;
u8 *raw_payload; u8 *raw_payload;
u8 payload_frames;
}; };
/** /**