You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

201 lines
5.7 KiB

#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 SECURITY_PARAMETER 32
#define NUM_MAX_HOPS 20
#define PAYLOAD_SIZE 32
#define HOP_DATA_SIZE (1 + SECURITY_PARAMETER + PAYLOAD_SIZE)
#define ROUTING_INFO_SIZE (HOP_DATA_SIZE * NUM_MAX_HOPS)
#define TOTAL_PACKET_SIZE (1 + 33 + SECURITY_PARAMETER + ROUTING_INFO_SIZE)
struct onionpacket {
/* Cleartext information */
u8 version;
u8 mac[SECURITY_PARAMETER];
struct pubkey ephemeralkey;
/* Encrypted information */
u8 routinginfo[ROUTING_INFO_SIZE];
};
enum route_next_case {
ONION_END = 0,
ONION_FORWARD = 1,
};
/* BOLT #4:
*
* The `hops_data` field is a structure that holds obfuscations of the
* next hop's address, transfer information, and its associated HMAC. It is
* 1300 bytes (`20x65`) long and has the following structure:
*
* 1. type: `hops_data`
* 2. data:
* * [`1`:`realm`]
* * [`32`:`per_hop`]
* * [`32`:`HMAC`]
* * ...
* * `filler`
*
* Where, the `realm`, `per_hop` (with contents dependent on `realm`), and `HMAC`
* are repeated for each hop; and where, `filler` consists of obfuscated,
* deterministically-generated padding, as detailed in
* [Filler Generation](#filler-generation). Additionally, `hops_data` is
* incrementally obfuscated at each hop.
*
* The `realm` byte determines the format of the `per_hop` field; currently, only
* `realm` 0 is defined, for which the `per_hop` format follows:
*
* 1. type: `per_hop` (for `realm` 0)
* 2. data:
* * [`8`:`short_channel_id`]
* * [`8`:`amt_to_forward`]
* * [`4`:`outgoing_cltv_value`]
* * [`12`:`padding`]
*/
struct hop_data {
u8 realm;
struct short_channel_id channel_id;
struct amount_msat amt_forward;
u32 outgoing_cltv;
/* Padding omitted, will be zeroed */
u8 hmac[SECURITY_PARAMETER];
};
struct route_step {
enum route_next_case nextcase;
struct onionpacket *next;
struct hop_data hop_data;
};
/**
* 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 pubkey path[],
struct hop_data hops_data[],
const u8 * sessionkey,
const u8 *assocdata,
const size_t assocdatalen,
struct secret **path_secrets
);
/**
* onion_shared_secret - calculate ECDH shared secret between nodes.
*
* @secret: the shared secret (32 bytes long)
* @pubkey: the public key of the other node
* @privkey: the private key of this node (32 bytes long)
*/
bool onion_shared_secret(
u8 *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 u8 *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.
*
* @ctx: tal context to allocate from
* @src: buffer to read the packet from
* @srclen: length of the @src (must be TOTAL_PACKET_SIZE)
* @why_bad: if NULL return, this is what was wrong with the packet.
*/
struct onionpacket *parse_onionpacket(const tal_t *ctx,
const void *src,
const size_t srclen,
enum onion_type *why_bad);
struct onionreply {
/* Node index in the path that is replying */
int origin_index;
u8 *msg;
};
/**
* 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)
*/
u8 *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
*/
u8 *wrap_onionreply(const tal_t *ctx, const struct secret *shared_secret,
const u8 *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
*/
struct onionreply *unwrap_onionreply(const tal_t *ctx,
const struct secret *shared_secrets,
const int numhops, const u8 *reply);
#endif /* LIGHTNING_COMMON_SPHINX_H */