mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 07:04:22 +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>
|
||||
|
||||
#define BLINDING_FACTOR_SIZE 32
|
||||
#define KEY_LEN 32
|
||||
|
||||
#define NUM_STREAM_BYTES (2*ROUTING_INFO_SIZE)
|
||||
#define ONION_REPLY_SIZE 256
|
||||
@@ -34,10 +33,7 @@ struct hop_params {
|
||||
};
|
||||
|
||||
struct keyset {
|
||||
u8 pi[KEY_LEN];
|
||||
u8 mu[KEY_LEN];
|
||||
u8 rho[KEY_LEN];
|
||||
u8 gamma[KEY_LEN];
|
||||
struct secret pi, mu, rho, gamma;
|
||||
};
|
||||
|
||||
/* 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
|
||||
* 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 };
|
||||
|
||||
crypto_stream_chacha20(dst, dstlen, nonce, k);
|
||||
crypto_stream_chacha20(dst, dstlen, nonce, k->data);
|
||||
}
|
||||
|
||||
/* 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 };
|
||||
|
||||
crypto_stream_chacha20_xor(dst, dst, dstlen, nonce, k);
|
||||
crypto_stream_chacha20_xor(dst, dst, dstlen, nonce, k->data);
|
||||
}
|
||||
|
||||
static bool compute_hmac(
|
||||
@@ -219,7 +215,7 @@ static bool compute_hmac(
|
||||
|
||||
static void compute_packet_hmac(const struct onionpacket *packet,
|
||||
const u8 *assocdata, const size_t assocdatalen,
|
||||
u8 *mukey, u8 *hmac)
|
||||
const struct secret *mukey, u8 *hmac)
|
||||
{
|
||||
u8 mactemp[ROUTING_INFO_SIZE + assocdatalen];
|
||||
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, 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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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,
|
||||
@@ -243,7 +239,7 @@ static bool generate_header_padding(void *dst, size_t dstlen,
|
||||
struct hop_params *params)
|
||||
{
|
||||
u8 stream[2 * ROUTING_INFO_SIZE];
|
||||
u8 key[KEY_LEN];
|
||||
struct secret key;
|
||||
size_t fillerStart, fillerEnd, fillerSize;
|
||||
|
||||
memset(dst, 0, dstlen);
|
||||
@@ -252,7 +248,7 @@ static bool generate_header_padding(void *dst, size_t dstlen,
|
||||
¶ms[i].secret))
|
||||
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,
|
||||
* 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)
|
||||
{
|
||||
u8 stream[2 * ROUTING_INFO_SIZE];
|
||||
u8 key[KEY_LEN];
|
||||
struct secret key;
|
||||
size_t fillerStart, fillerSize;
|
||||
|
||||
memset(dst, 0, dstlen);
|
||||
@@ -288,7 +284,7 @@ static bool generate_prefill(void *dst, size_t dstlen,
|
||||
¶ms[i].secret))
|
||||
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,
|
||||
* 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,
|
||||
struct keyset *keys)
|
||||
{
|
||||
generate_key(keys->rho, "rho", 3, secret);
|
||||
generate_key(keys->pi, "pi", 2, secret);
|
||||
generate_key(keys->mu, "mu", 2, secret);
|
||||
generate_key(keys->gamma, "gamma", 5, secret);
|
||||
generate_key(&keys->rho, "rho", 3, secret);
|
||||
generate_key(&keys->pi, "pi", 2, secret);
|
||||
generate_key(&keys->mu, "mu", 2, secret);
|
||||
generate_key(&keys->gamma, "gamma", 5, secret);
|
||||
}
|
||||
|
||||
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,
|
||||
const struct secret *shared_secret)
|
||||
{
|
||||
u8 padkey[KEY_LEN];
|
||||
generate_key(padkey, "prefill", 7, shared_secret);
|
||||
xor_cipher_stream(dst, padkey, dstlen);
|
||||
struct secret padkey;
|
||||
generate_key(&padkey, "prefill", 7, shared_secret);
|
||||
xor_cipher_stream(dst, &padkey, dstlen);
|
||||
}
|
||||
|
||||
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]);
|
||||
u8 filler[fillerSize];
|
||||
struct keyset keys;
|
||||
u8 padkey[KEY_LEN];
|
||||
struct secret padkey;
|
||||
u8 nexthmac[HMAC_SIZE];
|
||||
struct hop_params *params;
|
||||
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
|
||||
* overwritten below or above anyway. */
|
||||
generate_key(padkey, "pad", 3, sp->session_key);
|
||||
generate_cipher_stream(packet->routinginfo, padkey, ROUTING_INFO_SIZE);
|
||||
generate_key(&padkey, "pad", 3, sp->session_key);
|
||||
generate_cipher_stream(packet->routinginfo, &padkey, ROUTING_INFO_SIZE);
|
||||
|
||||
generate_header_padding(filler, sizeof(filler), sp, params);
|
||||
|
||||
@@ -529,14 +525,14 @@ struct onionpacket *create_onionpacket(
|
||||
memmove(packet->routinginfo + shiftSize, packet->routinginfo,
|
||||
ROUTING_INFO_SIZE-shiftSize);
|
||||
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);
|
||||
|
||||
if (i == num_hops - 1) {
|
||||
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);
|
||||
}
|
||||
memcpy(packet->mac, nexthmac, sizeof(nexthmac));
|
||||
@@ -580,7 +576,7 @@ struct route_step *process_onionpacket(
|
||||
step->next->version = msg->version;
|
||||
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
|
||||
|| IFDEV(dev_fail_process_onionpacket, false)) {
|
||||
@@ -591,7 +587,7 @@ struct route_step *process_onionpacket(
|
||||
//FIXME:store seen secrets to avoid replay attacks
|
||||
memset(paddedheader, 0, sizeof(paddedheader));
|
||||
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);
|
||||
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;
|
||||
struct onionreply *reply = tal(ctx, struct onionreply);
|
||||
u8 *payload = tal_arr(ctx, u8, 0);
|
||||
u8 key[KEY_LEN];
|
||||
struct secret key;
|
||||
u8 hmac[HMAC_SIZE];
|
||||
|
||||
/* 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,
|
||||
* 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),
|
||||
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 onionreply *reply)
|
||||
{
|
||||
u8 key[KEY_LEN];
|
||||
struct secret key;
|
||||
struct onionreply *result = tal(ctx, struct onionreply);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
generate_key(key, "ammag", 5, shared_secret);
|
||||
generate_key(&key, "ammag", 5, shared_secret);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -709,7 +705,8 @@ u8 *unwrap_onionreply(const tal_t *ctx,
|
||||
int *origin_index)
|
||||
{
|
||||
struct onionreply *r;
|
||||
u8 key[KEY_LEN], hmac[HMAC_SIZE];
|
||||
struct secret key;
|
||||
u8 hmac[HMAC_SIZE];
|
||||
const u8 *cursor;
|
||||
u8 *final;
|
||||
size_t max;
|
||||
@@ -729,10 +726,10 @@ u8 *unwrap_onionreply(const tal_t *ctx,
|
||||
|
||||
/* Check if the HMAC matches, this means that this is
|
||||
* 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),
|
||||
tal_count(r->contents) - sizeof(hmac),
|
||||
key, KEY_LEN);
|
||||
key.data, sizeof(key.data));
|
||||
if (memcmp(hmac, r->contents, sizeof(hmac)) == 0) {
|
||||
*origin_index = i;
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user