diff --git a/lightningd/sphinx.c b/lightningd/sphinx.c index a0a941451..d04f2ca30 100644 --- a/lightningd/sphinx.c +++ b/lightningd/sphinx.c @@ -479,16 +479,41 @@ u8 *create_onionreply(const tal_t *ctx, const struct secret *shared_secret, u8 key[KEY_LEN]; u8 hmac[HMAC_SIZE]; + /* BOLT #4: + * + * The node returning the message builds a return packet consisting of + * the following fields: + * + * 1. data: + * * [`32`:`hmac`] + * * [`2`:`failure_len`] + * * [`failure_len`:`failuremsg`] + * * [`2`:`pad_len`] + * * [`pad_len`:`pad`] + */ towire_u16(&payload, msglen); towire(&payload, failure_msg, msglen); towire_u16(&payload, padlen); towire_pad(&payload, padlen); + + /* BOLT #4: + * + * The node SHOULD set `pad` such that the `failure_len` plus + * `pad_len` is equal to 128. This is 28 bytes longer than then the + * longest currently-defined message. + */ assert(tal_len(payload) == ONION_REPLY_SIZE + 4); + /* BOLT #4: + * + * Where `hmac` is an HMAC authenticating the remainder of the packet, + * with a key using the above key generation with key type "_um_" + */ generate_key(key, "um", 2, shared_secret->data); compute_hmac(hmac, payload, tal_len(payload), key, KEY_LEN); towire(&reply, hmac, sizeof(hmac)); + towire(&reply, payload, tal_len(payload)); tal_free(payload); @@ -502,6 +527,15 @@ u8 *wrap_onionreply(const tal_t *ctx, size_t streamlen = tal_len(reply); u8 stream[streamlen]; u8 *result = tal_arr(ctx, u8, streamlen); + + /* BOLT #4: + * + * The node then generates a new key, using the key type `ammag`. + * This key is then used to generate a pseudo-random stream, which is + * then applied to the packet using `XOR`. + * + * The obfuscation step is repeated by every node on the return path. + */ generate_key(key, "ammag", 5, shared_secret->data); generate_cipher_stream(stream, key, streamlen); xorbytes(result, stream, reply, streamlen);