mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 15:14:23 +01:00
common: make sphinx use struct secret internally.
We don't have a struct symkey, though perhaps we should? Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -20,7 +20,6 @@
|
|||||||
#include <wire/wire.h>
|
#include <wire/wire.h>
|
||||||
|
|
||||||
#define BLINDING_FACTOR_SIZE 32
|
#define BLINDING_FACTOR_SIZE 32
|
||||||
#define KEY_LEN 32
|
|
||||||
|
|
||||||
#define NUM_STREAM_BYTES (2*ROUTING_INFO_SIZE)
|
#define NUM_STREAM_BYTES (2*ROUTING_INFO_SIZE)
|
||||||
#define ONION_REPLY_SIZE 256
|
#define ONION_REPLY_SIZE 256
|
||||||
@@ -34,10 +33,7 @@ struct hop_params {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct keyset {
|
struct keyset {
|
||||||
u8 pi[KEY_LEN];
|
struct secret pi, mu, rho, gamma;
|
||||||
u8 mu[KEY_LEN];
|
|
||||||
u8 rho[KEY_LEN];
|
|
||||||
u8 gamma[KEY_LEN];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Encapsulates the information about a given payment path for the the onion
|
/* Encapsulates the information about a given payment path for the the onion
|
||||||
@@ -187,19 +183,19 @@ static void xorbytes(uint8_t *d, const uint8_t *a, const uint8_t *b, size_t len)
|
|||||||
* Generate a pseudo-random byte stream of length `dstlen` from key `k` and
|
* Generate a pseudo-random byte stream of length `dstlen` from key `k` and
|
||||||
* store it in `dst`. `dst must be at least `dstlen` bytes long.
|
* store it in `dst`. `dst must be at least `dstlen` bytes long.
|
||||||
*/
|
*/
|
||||||
static void generate_cipher_stream(void *dst, const u8 *k, size_t dstlen)
|
static void generate_cipher_stream(void *dst, const struct secret *k, size_t dstlen)
|
||||||
{
|
{
|
||||||
const u8 nonce[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
const u8 nonce[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
|
|
||||||
crypto_stream_chacha20(dst, dstlen, nonce, k);
|
crypto_stream_chacha20(dst, dstlen, nonce, k->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* xor cipher stream into dst */
|
/* xor cipher stream into dst */
|
||||||
static void xor_cipher_stream(void *dst, const u8 *k, size_t dstlen)
|
static void xor_cipher_stream(void *dst, const struct secret *k, size_t dstlen)
|
||||||
{
|
{
|
||||||
const u8 nonce[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
const u8 nonce[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
|
|
||||||
crypto_stream_chacha20_xor(dst, dst, dstlen, nonce, k);
|
crypto_stream_chacha20_xor(dst, dst, dstlen, nonce, k->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool compute_hmac(
|
static bool compute_hmac(
|
||||||
@@ -219,7 +215,7 @@ static bool compute_hmac(
|
|||||||
|
|
||||||
static void compute_packet_hmac(const struct onionpacket *packet,
|
static void compute_packet_hmac(const struct onionpacket *packet,
|
||||||
const u8 *assocdata, const size_t assocdatalen,
|
const u8 *assocdata, const size_t assocdatalen,
|
||||||
u8 *mukey, u8 *hmac)
|
const struct secret *mukey, u8 *hmac)
|
||||||
{
|
{
|
||||||
u8 mactemp[ROUTING_INFO_SIZE + assocdatalen];
|
u8 mactemp[ROUTING_INFO_SIZE + assocdatalen];
|
||||||
u8 mac[32];
|
u8 mac[32];
|
||||||
@@ -228,14 +224,14 @@ static void compute_packet_hmac(const struct onionpacket *packet,
|
|||||||
write_buffer(mactemp, packet->routinginfo, ROUTING_INFO_SIZE, &pos);
|
write_buffer(mactemp, packet->routinginfo, ROUTING_INFO_SIZE, &pos);
|
||||||
write_buffer(mactemp, assocdata, assocdatalen, &pos);
|
write_buffer(mactemp, assocdata, assocdatalen, &pos);
|
||||||
|
|
||||||
compute_hmac(mac, mactemp, sizeof(mactemp), mukey, KEY_LEN);
|
compute_hmac(mac, mactemp, sizeof(mactemp), mukey->data, sizeof(mukey->data));
|
||||||
memcpy(hmac, mac, HMAC_SIZE);
|
memcpy(hmac, mac, HMAC_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool generate_key(void *k, const char *t, u8 tlen,
|
static bool generate_key(struct secret *k, const char *t, u8 tlen,
|
||||||
const struct secret *s)
|
const struct secret *s)
|
||||||
{
|
{
|
||||||
return compute_hmac(k, s->data, KEY_LEN, t, tlen);
|
return compute_hmac(k->data, s->data, sizeof(s->data), t, tlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool generate_header_padding(void *dst, size_t dstlen,
|
static bool generate_header_padding(void *dst, size_t dstlen,
|
||||||
@@ -243,7 +239,7 @@ static bool generate_header_padding(void *dst, size_t dstlen,
|
|||||||
struct hop_params *params)
|
struct hop_params *params)
|
||||||
{
|
{
|
||||||
u8 stream[2 * ROUTING_INFO_SIZE];
|
u8 stream[2 * ROUTING_INFO_SIZE];
|
||||||
u8 key[KEY_LEN];
|
struct secret key;
|
||||||
size_t fillerStart, fillerEnd, fillerSize;
|
size_t fillerStart, fillerEnd, fillerSize;
|
||||||
|
|
||||||
memset(dst, 0, dstlen);
|
memset(dst, 0, dstlen);
|
||||||
@@ -252,7 +248,7 @@ static bool generate_header_padding(void *dst, size_t dstlen,
|
|||||||
¶ms[i].secret))
|
¶ms[i].secret))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
generate_cipher_stream(stream, key, sizeof(stream));
|
generate_cipher_stream(stream, &key, sizeof(stream));
|
||||||
|
|
||||||
/* Sum up how many bytes have been used by previous hops,
|
/* Sum up how many bytes have been used by previous hops,
|
||||||
* that gives us the start in the stream */
|
* that gives us the start in the stream */
|
||||||
@@ -279,7 +275,7 @@ static bool generate_prefill(void *dst, size_t dstlen,
|
|||||||
struct hop_params *params)
|
struct hop_params *params)
|
||||||
{
|
{
|
||||||
u8 stream[2 * ROUTING_INFO_SIZE];
|
u8 stream[2 * ROUTING_INFO_SIZE];
|
||||||
u8 key[KEY_LEN];
|
struct secret key;
|
||||||
size_t fillerStart, fillerSize;
|
size_t fillerStart, fillerSize;
|
||||||
|
|
||||||
memset(dst, 0, dstlen);
|
memset(dst, 0, dstlen);
|
||||||
@@ -288,7 +284,7 @@ static bool generate_prefill(void *dst, size_t dstlen,
|
|||||||
¶ms[i].secret))
|
¶ms[i].secret))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
generate_cipher_stream(stream, key, sizeof(stream));
|
generate_cipher_stream(stream, &key, sizeof(stream));
|
||||||
|
|
||||||
/* Sum up how many bytes have been used by previous hops,
|
/* Sum up how many bytes have been used by previous hops,
|
||||||
* that gives us the start in the stream */
|
* that gives us the start in the stream */
|
||||||
@@ -355,10 +351,10 @@ bool onion_shared_secret(
|
|||||||
static void generate_key_set(const struct secret *secret,
|
static void generate_key_set(const struct secret *secret,
|
||||||
struct keyset *keys)
|
struct keyset *keys)
|
||||||
{
|
{
|
||||||
generate_key(keys->rho, "rho", 3, secret);
|
generate_key(&keys->rho, "rho", 3, secret);
|
||||||
generate_key(keys->pi, "pi", 2, secret);
|
generate_key(&keys->pi, "pi", 2, secret);
|
||||||
generate_key(keys->mu, "mu", 2, secret);
|
generate_key(&keys->mu, "mu", 2, secret);
|
||||||
generate_key(keys->gamma, "gamma", 5, secret);
|
generate_key(&keys->gamma, "gamma", 5, secret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct hop_params *generate_hop_params(
|
static struct hop_params *generate_hop_params(
|
||||||
@@ -434,9 +430,9 @@ static void sphinx_write_frame(u8 *dest, const struct sphinx_hop *hop)
|
|||||||
static void sphinx_prefill_stream_xor(u8 *dst, size_t dstlen,
|
static void sphinx_prefill_stream_xor(u8 *dst, size_t dstlen,
|
||||||
const struct secret *shared_secret)
|
const struct secret *shared_secret)
|
||||||
{
|
{
|
||||||
u8 padkey[KEY_LEN];
|
struct secret padkey;
|
||||||
generate_key(padkey, "prefill", 7, shared_secret);
|
generate_key(&padkey, "prefill", 7, shared_secret);
|
||||||
xor_cipher_stream(dst, padkey, dstlen);
|
xor_cipher_stream(dst, &padkey, dstlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sphinx_prefill(u8 *routinginfo, const struct sphinx_path *sp,
|
static void sphinx_prefill(u8 *routinginfo, const struct sphinx_path *sp,
|
||||||
@@ -476,7 +472,7 @@ struct onionpacket *create_onionpacket(
|
|||||||
sphinx_hop_size(&sp->hops[num_hops - 1]);
|
sphinx_hop_size(&sp->hops[num_hops - 1]);
|
||||||
u8 filler[fillerSize];
|
u8 filler[fillerSize];
|
||||||
struct keyset keys;
|
struct keyset keys;
|
||||||
u8 padkey[KEY_LEN];
|
struct secret padkey;
|
||||||
u8 nexthmac[HMAC_SIZE];
|
u8 nexthmac[HMAC_SIZE];
|
||||||
struct hop_params *params;
|
struct hop_params *params;
|
||||||
struct secret *secrets = tal_arr(ctx, struct secret, num_hops);
|
struct secret *secrets = tal_arr(ctx, struct secret, num_hops);
|
||||||
@@ -510,8 +506,8 @@ struct onionpacket *create_onionpacket(
|
|||||||
*/
|
*/
|
||||||
/* Note that this is just hop_payloads: the rest of the packet is
|
/* Note that this is just hop_payloads: the rest of the packet is
|
||||||
* overwritten below or above anyway. */
|
* overwritten below or above anyway. */
|
||||||
generate_key(padkey, "pad", 3, sp->session_key);
|
generate_key(&padkey, "pad", 3, sp->session_key);
|
||||||
generate_cipher_stream(packet->routinginfo, padkey, ROUTING_INFO_SIZE);
|
generate_cipher_stream(packet->routinginfo, &padkey, ROUTING_INFO_SIZE);
|
||||||
|
|
||||||
generate_header_padding(filler, sizeof(filler), sp, params);
|
generate_header_padding(filler, sizeof(filler), sp, params);
|
||||||
|
|
||||||
@@ -529,14 +525,14 @@ struct onionpacket *create_onionpacket(
|
|||||||
memmove(packet->routinginfo + shiftSize, packet->routinginfo,
|
memmove(packet->routinginfo + shiftSize, packet->routinginfo,
|
||||||
ROUTING_INFO_SIZE-shiftSize);
|
ROUTING_INFO_SIZE-shiftSize);
|
||||||
sphinx_write_frame(packet->routinginfo, &sp->hops[i]);
|
sphinx_write_frame(packet->routinginfo, &sp->hops[i]);
|
||||||
xor_cipher_stream(packet->routinginfo, keys.rho,
|
xor_cipher_stream(packet->routinginfo, &keys.rho,
|
||||||
ROUTING_INFO_SIZE);
|
ROUTING_INFO_SIZE);
|
||||||
|
|
||||||
if (i == num_hops - 1) {
|
if (i == num_hops - 1) {
|
||||||
memcpy(packet->routinginfo + ROUTING_INFO_SIZE - fillerSize, filler, fillerSize);
|
memcpy(packet->routinginfo + ROUTING_INFO_SIZE - fillerSize, filler, fillerSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
compute_packet_hmac(packet, sp->associated_data, tal_bytelen(sp->associated_data), keys.mu,
|
compute_packet_hmac(packet, sp->associated_data, tal_bytelen(sp->associated_data), &keys.mu,
|
||||||
nexthmac);
|
nexthmac);
|
||||||
}
|
}
|
||||||
memcpy(packet->mac, nexthmac, sizeof(nexthmac));
|
memcpy(packet->mac, nexthmac, sizeof(nexthmac));
|
||||||
@@ -580,7 +576,7 @@ struct route_step *process_onionpacket(
|
|||||||
step->next->version = msg->version;
|
step->next->version = msg->version;
|
||||||
generate_key_set(shared_secret, &keys);
|
generate_key_set(shared_secret, &keys);
|
||||||
|
|
||||||
compute_packet_hmac(msg, assocdata, assocdatalen, keys.mu, hmac);
|
compute_packet_hmac(msg, assocdata, assocdatalen, &keys.mu, hmac);
|
||||||
|
|
||||||
if (memcmp(msg->mac, hmac, sizeof(hmac)) != 0
|
if (memcmp(msg->mac, hmac, sizeof(hmac)) != 0
|
||||||
|| IFDEV(dev_fail_process_onionpacket, false)) {
|
|| IFDEV(dev_fail_process_onionpacket, false)) {
|
||||||
@@ -591,7 +587,7 @@ struct route_step *process_onionpacket(
|
|||||||
//FIXME:store seen secrets to avoid replay attacks
|
//FIXME:store seen secrets to avoid replay attacks
|
||||||
memset(paddedheader, 0, sizeof(paddedheader));
|
memset(paddedheader, 0, sizeof(paddedheader));
|
||||||
memcpy(paddedheader, msg->routinginfo, ROUTING_INFO_SIZE);
|
memcpy(paddedheader, msg->routinginfo, ROUTING_INFO_SIZE);
|
||||||
xor_cipher_stream(paddedheader, keys.rho, sizeof(paddedheader));
|
xor_cipher_stream(paddedheader, &keys.rho, sizeof(paddedheader));
|
||||||
|
|
||||||
compute_blinding_factor(&msg->ephemeralkey, shared_secret, blind);
|
compute_blinding_factor(&msg->ephemeralkey, shared_secret, blind);
|
||||||
if (!blind_group_element(&step->next->ephemeralkey, &msg->ephemeralkey, blind))
|
if (!blind_group_element(&step->next->ephemeralkey, &msg->ephemeralkey, blind))
|
||||||
@@ -633,7 +629,7 @@ struct onionreply *create_onionreply(const tal_t *ctx,
|
|||||||
size_t padlen = ONION_REPLY_SIZE - msglen;
|
size_t padlen = ONION_REPLY_SIZE - msglen;
|
||||||
struct onionreply *reply = tal(ctx, struct onionreply);
|
struct onionreply *reply = tal(ctx, struct onionreply);
|
||||||
u8 *payload = tal_arr(ctx, u8, 0);
|
u8 *payload = tal_arr(ctx, u8, 0);
|
||||||
u8 key[KEY_LEN];
|
struct secret key;
|
||||||
u8 hmac[HMAC_SIZE];
|
u8 hmac[HMAC_SIZE];
|
||||||
|
|
||||||
/* BOLT #4:
|
/* BOLT #4:
|
||||||
@@ -669,9 +665,9 @@ struct onionreply *create_onionreply(const tal_t *ctx,
|
|||||||
* Where `hmac` is an HMAC authenticating the remainder of the packet,
|
* Where `hmac` is an HMAC authenticating the remainder of the packet,
|
||||||
* with a key generated using the above process, with key type `um`
|
* with a key generated using the above process, with key type `um`
|
||||||
*/
|
*/
|
||||||
generate_key(key, "um", 2, shared_secret);
|
generate_key(&key, "um", 2, shared_secret);
|
||||||
|
|
||||||
compute_hmac(hmac, payload, tal_count(payload), key, KEY_LEN);
|
compute_hmac(hmac, payload, tal_count(payload), key.data, sizeof(key.data));
|
||||||
reply->contents = tal_arr(reply, u8, 0),
|
reply->contents = tal_arr(reply, u8, 0),
|
||||||
towire(&reply->contents, hmac, sizeof(hmac));
|
towire(&reply->contents, hmac, sizeof(hmac));
|
||||||
|
|
||||||
@@ -685,7 +681,7 @@ struct onionreply *wrap_onionreply(const tal_t *ctx,
|
|||||||
const struct secret *shared_secret,
|
const struct secret *shared_secret,
|
||||||
const struct onionreply *reply)
|
const struct onionreply *reply)
|
||||||
{
|
{
|
||||||
u8 key[KEY_LEN];
|
struct secret key;
|
||||||
struct onionreply *result = tal(ctx, struct onionreply);
|
struct onionreply *result = tal(ctx, struct onionreply);
|
||||||
|
|
||||||
/* BOLT #4:
|
/* BOLT #4:
|
||||||
@@ -696,9 +692,9 @@ struct onionreply *wrap_onionreply(const tal_t *ctx,
|
|||||||
*
|
*
|
||||||
* The obfuscation step is repeated by every hop along the return path.
|
* The obfuscation step is repeated by every hop along the return path.
|
||||||
*/
|
*/
|
||||||
generate_key(key, "ammag", 5, shared_secret);
|
generate_key(&key, "ammag", 5, shared_secret);
|
||||||
result->contents = tal_dup_talarr(result, u8, reply->contents);
|
result->contents = tal_dup_talarr(result, u8, reply->contents);
|
||||||
xor_cipher_stream(result->contents, key, tal_bytelen(result->contents));
|
xor_cipher_stream(result->contents, &key, tal_bytelen(result->contents));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -709,7 +705,8 @@ u8 *unwrap_onionreply(const tal_t *ctx,
|
|||||||
int *origin_index)
|
int *origin_index)
|
||||||
{
|
{
|
||||||
struct onionreply *r;
|
struct onionreply *r;
|
||||||
u8 key[KEY_LEN], hmac[HMAC_SIZE];
|
struct secret key;
|
||||||
|
u8 hmac[HMAC_SIZE];
|
||||||
const u8 *cursor;
|
const u8 *cursor;
|
||||||
u8 *final;
|
u8 *final;
|
||||||
size_t max;
|
size_t max;
|
||||||
@@ -729,10 +726,10 @@ u8 *unwrap_onionreply(const tal_t *ctx,
|
|||||||
|
|
||||||
/* Check if the HMAC matches, this means that this is
|
/* Check if the HMAC matches, this means that this is
|
||||||
* the origin */
|
* the origin */
|
||||||
generate_key(key, "um", 2, &shared_secrets[i]);
|
generate_key(&key, "um", 2, &shared_secrets[i]);
|
||||||
compute_hmac(hmac, r->contents + sizeof(hmac),
|
compute_hmac(hmac, r->contents + sizeof(hmac),
|
||||||
tal_count(r->contents) - sizeof(hmac),
|
tal_count(r->contents) - sizeof(hmac),
|
||||||
key, KEY_LEN);
|
key.data, sizeof(key.data));
|
||||||
if (memcmp(hmac, r->contents, sizeof(hmac)) == 0) {
|
if (memcmp(hmac, r->contents, sizeof(hmac)) == 0) {
|
||||||
*origin_index = i;
|
*origin_index = i;
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user