#ifndef LIGHTNING_COMMON_SPHINX_H #define LIGHTNING_COMMON_SPHINX_H #include "config.h" #include "bitcoin/privkey.h" #include "bitcoin/pubkey.h" #include #include #include #include #include #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]; }; struct sphinx_compressed_onion { u8 version; struct pubkey ephemeralkey; u8 *routinginfo; u8 mac[HMAC_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 * @has_realm: used for HTLCs, where first byte 0 is magical. */ 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, bool has_realm ); /** * 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); /** * Set the rendez-vous node_id and make the onion generated from the * sphinx_path compressible. To unset pass in a NULL rendezvous_id. * * Returns false if there was an error converting from the node_id to a public * key. */ bool sphinx_path_set_rendezvous(struct sphinx_path *sp, const struct node_id *rendezvous_id); /** * Given a compressed onion expand it by re-generating the prefiller and * inserting it in the appropriate place. */ struct onionpacket *sphinx_decompress(const tal_t *ctx, const struct sphinx_compressed_onion *src, const struct secret *shared_secret); /** * Use ECDH to generate a shared secret from a privkey and a pubkey. * * Sphinx uses shared secrets derived from a private key and a public key * using ECDH in a number of places. This is a simple wrapper around the * secp256k1 functions, with our internal types. */ bool sphinx_create_shared_secret(struct secret *privkey, const struct pubkey *pubkey, const struct secret *secret); /** * Given a compressible onionpacket, return the compressed version. */ struct sphinx_compressed_onion * sphinx_compress(const tal_t *ctx, const struct onionpacket *packet, const struct sphinx_path *path); u8 *sphinx_compressed_onion_serialize( const tal_t *ctx, const struct sphinx_compressed_onion *onion); struct sphinx_compressed_onion * sphinx_compressed_onion_deserialize(const tal_t *ctx, const u8 *src); #if DEVELOPER /* Override to force us to reject valid onion packets */ extern bool dev_fail_process_onionpacket; #endif #endif /* LIGHTNING_COMMON_SPHINX_H */