mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-08 14:50:26 +01:00
262e4c840f
Generally I prefer structures over u8, since the size is enforced at runtime; and in several places we were doing conversions as the code using Sphinx does treat struct secret as type of the secret. Note that passing an array is the same as passing the address, so changing from 'u8 secret[32]' to 'struct secret secret' means various 'secret' parameters change to '&secret'. Technically, '&secret' also would have worked before, since '&' is a noop on array, but that's always seemed a bit weird. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
231 lines
6.5 KiB
C
231 lines
6.5 KiB
C
#ifndef LIGHTNING_COMMON_SPHINX_H
|
|
#define LIGHTNING_COMMON_SPHINX_H
|
|
|
|
#include "config.h"
|
|
#include "bitcoin/privkey.h"
|
|
#include "bitcoin/pubkey.h"
|
|
|
|
#include <ccan/short_types/short_types.h>
|
|
#include <ccan/tal/tal.h>
|
|
#include <secp256k1.h>
|
|
#include <sodium/randombytes.h>
|
|
#include <wire/gen_onion_wire.h>
|
|
#include <wire/wire.h>
|
|
|
|
#define VERSION_SIZE 1
|
|
#define REALM_SIZE 1
|
|
#define HMAC_SIZE 32
|
|
#define PUBKEY_SIZE 33
|
|
#define FRAME_SIZE 65
|
|
#define ROUTING_INFO_SIZE 1300
|
|
#define TOTAL_PACKET_SIZE (VERSION_SIZE + PUBKEY_SIZE + HMAC_SIZE + ROUTING_INFO_SIZE)
|
|
|
|
struct onionpacket {
|
|
/* Cleartext information */
|
|
u8 version;
|
|
u8 mac[HMAC_SIZE];
|
|
struct pubkey ephemeralkey;
|
|
|
|
/* Encrypted information */
|
|
u8 routinginfo[ROUTING_INFO_SIZE];
|
|
};
|
|
|
|
enum route_next_case {
|
|
ONION_END = 0,
|
|
ONION_FORWARD = 1,
|
|
};
|
|
|
|
/**
|
|
* A sphinx payment path.
|
|
*
|
|
* This struct defines a path a payment is taking through the Lightning
|
|
* Network, including the session_key used to generate secrets, the associated
|
|
* data that'll be included in the HMACs and the payloads at each hop in the
|
|
* path. The struct is opaque since it should not be modified externally. Use
|
|
* `sphinx_path_new` or `sphinx_path_new_with_key` (testing only) to create a
|
|
* new instance.
|
|
*/
|
|
struct sphinx_path;
|
|
|
|
/* BOLT #4:
|
|
*
|
|
* ## Legacy `hop_data` payload format
|
|
*
|
|
* The `hop_data` format is identified by a single `0x00`-byte length,
|
|
* for backward compatibility. Its payload is defined as:
|
|
*
|
|
* 1. type: `hop_data` (for `realm` 0)
|
|
* 2. data:
|
|
* * [`short_channel_id`:`short_channel_id`]
|
|
* * [`u64`:`amt_to_forward`]
|
|
* * [`u32`:`outgoing_cltv_value`]
|
|
* * [`12*byte`:`padding`]
|
|
*/
|
|
struct hop_data_legacy {
|
|
u8 realm;
|
|
struct short_channel_id channel_id;
|
|
struct amount_msat amt_forward;
|
|
u32 outgoing_cltv;
|
|
};
|
|
|
|
/*
|
|
* All the necessary information to generate a valid onion for this hop on a
|
|
* sphinx path. The payload is preserialized in order since the onion
|
|
* generation is payload agnostic. */
|
|
struct sphinx_hop {
|
|
struct pubkey pubkey;
|
|
const u8 *raw_payload;
|
|
u8 hmac[HMAC_SIZE];
|
|
};
|
|
|
|
struct route_step {
|
|
enum route_next_case nextcase;
|
|
struct onionpacket *next;
|
|
u8 *raw_payload;
|
|
};
|
|
|
|
/**
|
|
* create_onionpacket - Create a new onionpacket that can be routed
|
|
* over a path of intermediate nodes.
|
|
*
|
|
* @ctx: tal context to allocate from
|
|
* @path: public keys of nodes along the path.
|
|
* @hoppayloads: payloads destined for individual hosts (limited to
|
|
* HOP_PAYLOAD_SIZE bytes)
|
|
* @num_hops: path length in nodes
|
|
* @sessionkey: 32 byte random session key to derive secrets from
|
|
* @assocdata: associated data to commit to in HMACs
|
|
* @assocdatalen: length of the assocdata
|
|
* @path_secrets: (out) shared secrets generated for the entire path
|
|
*/
|
|
struct onionpacket *create_onionpacket(
|
|
const tal_t * ctx,
|
|
struct sphinx_path *sp,
|
|
struct secret **path_secrets
|
|
);
|
|
|
|
/**
|
|
* onion_shared_secret - calculate ECDH shared secret between nodes.
|
|
*
|
|
* @secret: the shared secret
|
|
* @pubkey: the public key of the other node
|
|
* @privkey: the private key of this node (32 bytes long)
|
|
*/
|
|
bool onion_shared_secret(
|
|
struct secret *secret,
|
|
const struct onionpacket *packet,
|
|
const struct privkey *privkey);
|
|
|
|
/**
|
|
* process_onionpacket - process an incoming packet by stripping one
|
|
* onion layer and return the packet for the next hop.
|
|
*
|
|
* @ctx: tal context to allocate from
|
|
* @packet: incoming packet being processed
|
|
* @shared_secret: the result of 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
|
|
*/
|
|
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
|
|
);
|
|
|
|
/**
|
|
* serialize_onionpacket - Serialize an onionpacket to a buffer.
|
|
*
|
|
* @ctx: tal context to allocate from
|
|
* @packet: the packet to serialize
|
|
*/
|
|
u8 *serialize_onionpacket(
|
|
const tal_t *ctx,
|
|
const struct onionpacket *packet);
|
|
|
|
/**
|
|
* parse_onionpacket - Parse an onionpacket from a buffer.
|
|
*
|
|
* @src: buffer to read the packet from
|
|
* @srclen: length of the @src (must be TOTAL_PACKET_SIZE)
|
|
* @dest: the destination into which we should parse the packet
|
|
*/
|
|
enum onion_type parse_onionpacket(const u8 *src,
|
|
const size_t srclen,
|
|
struct onionpacket *dest);
|
|
|
|
/**
|
|
* create_onionreply - Format a failure message so we can return it
|
|
*
|
|
* @ctx: tal context to allocate from
|
|
* @shared_secret: The shared secret used in the forward direction, used for the
|
|
* HMAC
|
|
* @failure_msg: message (must support tal_len)
|
|
*/
|
|
struct onionreply *create_onionreply(const tal_t *ctx,
|
|
const struct secret *shared_secret,
|
|
const u8 *failure_msg);
|
|
|
|
/**
|
|
* wrap_onionreply - Add another encryption layer to the reply.
|
|
*
|
|
* @ctx: tal context to allocate from
|
|
* @shared_secret: the shared secret associated with the HTLC, used for the
|
|
* encryption.
|
|
* @reply: the reply to wrap
|
|
*/
|
|
struct onionreply *wrap_onionreply(const tal_t *ctx,
|
|
const struct secret *shared_secret,
|
|
const struct onionreply *reply);
|
|
|
|
/**
|
|
* unwrap_onionreply - Remove layers, check integrity and parse reply
|
|
*
|
|
* @ctx: tal context to allocate from
|
|
* @shared_secrets: shared secrets from the forward path
|
|
* @numhops: path length and number of shared_secrets provided
|
|
* @reply: the incoming reply
|
|
* @origin_index: the index in the path where the reply came from (-1 if unknown)
|
|
*
|
|
* Reverses create_onionreply and wrap_onionreply.
|
|
*/
|
|
u8 *unwrap_onionreply(const tal_t *ctx,
|
|
const struct secret *shared_secrets,
|
|
const int numhops,
|
|
const struct onionreply *reply,
|
|
int *origin_index);
|
|
|
|
/**
|
|
* Create a new empty sphinx_path.
|
|
*
|
|
* The sphinx_path instance can then be decorated with other functions and
|
|
* passed to `create_onionpacket` to generate the packet.
|
|
*/
|
|
struct sphinx_path *sphinx_path_new(const tal_t *ctx,
|
|
const u8 *associated_data);
|
|
|
|
/**
|
|
* Create a new empty sphinx_path with a given `session_key`.
|
|
*
|
|
* This MUST NOT be used outside of tests and tools as it may leak the path
|
|
* details if the `session_key` is not randomly generated.
|
|
*/
|
|
struct sphinx_path *sphinx_path_new_with_key(const tal_t *ctx,
|
|
const u8 *associated_data,
|
|
const struct secret *session_key);
|
|
|
|
/**
|
|
* Add a payload hop to the path.
|
|
*/
|
|
void sphinx_add_hop(struct sphinx_path *path, const struct pubkey *pubkey,
|
|
const u8 *payload TAKES);
|
|
|
|
/**
|
|
* Compute the size of the serialized payloads.
|
|
*/
|
|
size_t sphinx_path_payloads_size(const struct sphinx_path *path);
|
|
|
|
#endif /* LIGHTNING_COMMON_SPHINX_H */
|