mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 15:14:23 +01:00
sphinx: Committing the onion packet to the payment-hash
The sphinx onion packet now commits to the HTLC payment-hash it is associated with. This prevents replay attacks with the same onion.
This commit is contained in:
committed by
Rusty Russell
parent
91b17d45d8
commit
cae283087d
@@ -442,7 +442,8 @@ static void json_sendpay(struct command *cmd,
|
|||||||
randombytes_buf(&sessionkey, sizeof(sessionkey));
|
randombytes_buf(&sessionkey, sizeof(sessionkey));
|
||||||
|
|
||||||
/* Onion will carry us from first peer onwards. */
|
/* Onion will carry us from first peer onwards. */
|
||||||
packet = create_onionpacket(cmd, ids, hoppayloads, sessionkey);
|
packet = create_onionpacket(cmd, ids, hoppayloads, sessionkey,
|
||||||
|
rhash.u.u8, sizeof(struct sha256));
|
||||||
onion = serialize_onionpacket(cmd, packet);
|
onion = serialize_onionpacket(cmd, packet);
|
||||||
|
|
||||||
if (pc)
|
if (pc)
|
||||||
|
|||||||
@@ -887,7 +887,8 @@ static void their_htlc_added(struct peer *peer, struct htlc *htlc,
|
|||||||
packet = parse_onionpacket(peer,
|
packet = parse_onionpacket(peer,
|
||||||
htlc->routing, tal_count(htlc->routing));
|
htlc->routing, tal_count(htlc->routing));
|
||||||
if (packet)
|
if (packet)
|
||||||
step = process_onionpacket(packet, packet, &pk);
|
step = process_onionpacket(packet, packet, &pk, htlc->rhash.u.u8,
|
||||||
|
sizeof(htlc->rhash));
|
||||||
|
|
||||||
if (!step) {
|
if (!step) {
|
||||||
log_unusual(peer->log, "Bad onion, failing HTLC %"PRIu64,
|
log_unusual(peer->log, "Bad onion, failing HTLC %"PRIu64,
|
||||||
@@ -4730,7 +4731,8 @@ static void json_newhtlc(struct command *cmd,
|
|||||||
hoppayloads = tal_arrz(cmd, struct hoppayload, 1);
|
hoppayloads = tal_arrz(cmd, struct hoppayload, 1);
|
||||||
memcpy(&path[0], peer->id, sizeof(struct pubkey));
|
memcpy(&path[0], peer->id, sizeof(struct pubkey));
|
||||||
randombytes_buf(&sessionkey, sizeof(sessionkey));
|
randombytes_buf(&sessionkey, sizeof(sessionkey));
|
||||||
packet = create_onionpacket(cmd, path, hoppayloads, sessionkey);
|
packet = create_onionpacket(cmd, path, hoppayloads, sessionkey,
|
||||||
|
rhash.u.u8, sizeof(rhash));
|
||||||
onion = serialize_onionpacket(cmd, packet);
|
onion = serialize_onionpacket(cmd, packet);
|
||||||
|
|
||||||
log_debug(peer->log, "JSON command to add new HTLC");
|
log_debug(peer->log, "JSON command to add new HTLC");
|
||||||
|
|||||||
@@ -159,13 +159,18 @@ static bool compute_hmac(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void compute_packet_hmac(const struct onionpacket *packet, u8 *mukey, u8 *hmac)
|
static void compute_packet_hmac(const struct onionpacket *packet,
|
||||||
|
const u8 *assocdata, const size_t assocdatalen,
|
||||||
|
u8 *mukey, u8 *hmac)
|
||||||
{
|
{
|
||||||
u8 mactemp[ROUTING_INFO_SIZE + TOTAL_HOP_PAYLOAD_SIZE];
|
u8 mactemp[ROUTING_INFO_SIZE + TOTAL_HOP_PAYLOAD_SIZE + assocdatalen];
|
||||||
u8 mac[32];
|
u8 mac[32];
|
||||||
|
int pos = 0;
|
||||||
|
|
||||||
|
write_buffer(mactemp, packet->routinginfo, ROUTING_INFO_SIZE, &pos);
|
||||||
|
write_buffer(mactemp, packet->hoppayloads, TOTAL_HOP_PAYLOAD_SIZE, &pos);
|
||||||
|
write_buffer(mactemp, assocdata, assocdatalen, &pos);
|
||||||
|
|
||||||
memcpy(mactemp, packet->routinginfo, ROUTING_INFO_SIZE);
|
|
||||||
memcpy(mactemp + ROUTING_INFO_SIZE, packet->hoppayloads, TOTAL_HOP_PAYLOAD_SIZE);
|
|
||||||
compute_hmac(mac, mactemp, sizeof(mactemp), mukey, KEY_LEN);
|
compute_hmac(mac, mactemp, sizeof(mactemp), mukey, KEY_LEN);
|
||||||
memcpy(hmac, mac, 20);
|
memcpy(hmac, mac, 20);
|
||||||
}
|
}
|
||||||
@@ -340,7 +345,9 @@ struct onionpacket *create_onionpacket(
|
|||||||
const tal_t *ctx,
|
const tal_t *ctx,
|
||||||
struct pubkey *path,
|
struct pubkey *path,
|
||||||
struct hoppayload hoppayloads[],
|
struct hoppayload hoppayloads[],
|
||||||
const u8 *sessionkey
|
const u8 *sessionkey,
|
||||||
|
const u8 *assocdata,
|
||||||
|
const size_t assocdatalen
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
struct onionpacket *packet = talz(ctx, struct onionpacket);
|
struct onionpacket *packet = talz(ctx, struct onionpacket);
|
||||||
@@ -394,7 +401,8 @@ struct onionpacket *create_onionpacket(
|
|||||||
memcpy(packet->hoppayloads + len, hopfiller, sizeof(hopfiller));
|
memcpy(packet->hoppayloads + len, hopfiller, sizeof(hopfiller));
|
||||||
}
|
}
|
||||||
|
|
||||||
compute_packet_hmac(packet, keys.mu, nexthmac);
|
compute_packet_hmac(packet, assocdata, assocdatalen, keys.mu,
|
||||||
|
nexthmac);
|
||||||
pubkey_hash160(nextaddr, &path[i]);
|
pubkey_hash160(nextaddr, &path[i]);
|
||||||
}
|
}
|
||||||
memcpy(packet->mac, nexthmac, sizeof(nexthmac));
|
memcpy(packet->mac, nexthmac, sizeof(nexthmac));
|
||||||
@@ -409,7 +417,9 @@ struct onionpacket *create_onionpacket(
|
|||||||
struct route_step *process_onionpacket(
|
struct route_step *process_onionpacket(
|
||||||
const tal_t *ctx,
|
const tal_t *ctx,
|
||||||
const struct onionpacket *msg,
|
const struct onionpacket *msg,
|
||||||
struct privkey *hop_privkey
|
struct privkey *hop_privkey,
|
||||||
|
const u8 *assocdata,
|
||||||
|
const size_t assocdatalen
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
struct route_step *step = talz(ctx, struct route_step);
|
struct route_step *step = talz(ctx, struct route_step);
|
||||||
@@ -427,7 +437,7 @@ struct route_step *process_onionpacket(
|
|||||||
create_shared_secret(secret, &msg->ephemeralkey, hop_privkey->secret);
|
create_shared_secret(secret, &msg->ephemeralkey, hop_privkey->secret);
|
||||||
generate_key_set(secret, &keys);
|
generate_key_set(secret, &keys);
|
||||||
|
|
||||||
compute_packet_hmac(msg, 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) {
|
||||||
warnx("Computed MAC does not match expected MAC, the message was modified.");
|
warnx("Computed MAC does not match expected MAC, the message was modified.");
|
||||||
|
|||||||
@@ -57,12 +57,16 @@ struct route_step {
|
|||||||
* HOP_PAYLOAD_SIZE bytes)
|
* HOP_PAYLOAD_SIZE bytes)
|
||||||
* @num_hops: path length in nodes
|
* @num_hops: path length in nodes
|
||||||
* @sessionkey: 20 byte random session key to derive secrets from
|
* @sessionkey: 20 byte random session key to derive secrets from
|
||||||
|
* @assocdata: associated data to commit to in HMACs
|
||||||
|
* @assocdatalen: length of the assocdata
|
||||||
*/
|
*/
|
||||||
struct onionpacket *create_onionpacket(
|
struct onionpacket *create_onionpacket(
|
||||||
const tal_t * ctx,
|
const tal_t * ctx,
|
||||||
struct pubkey path[],
|
struct pubkey path[],
|
||||||
struct hoppayload hoppayloads[],
|
struct hoppayload hoppayloads[],
|
||||||
const u8 * sessionkey
|
const u8 * sessionkey,
|
||||||
|
const u8 *assocdata,
|
||||||
|
const size_t assocdatalen
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,11 +77,15 @@ struct onionpacket *create_onionpacket(
|
|||||||
* @packet: incoming packet being processed
|
* @packet: incoming packet being processed
|
||||||
* @hop_privkey: the processing node's private key to decrypt the packet
|
* @hop_privkey: the processing node's private key to decrypt the packet
|
||||||
* @hoppayload: the per-hop payload destined for the processing node.
|
* @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(
|
struct route_step *process_onionpacket(
|
||||||
const tal_t * ctx,
|
const tal_t * ctx,
|
||||||
const struct onionpacket *packet,
|
const struct onionpacket *packet,
|
||||||
struct privkey *hop_privkey
|
struct privkey *hop_privkey,
|
||||||
|
const u8 *assocdata,
|
||||||
|
const size_t assocdatalen
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
bool generate = false, decode = false;
|
bool generate = false, decode = false;
|
||||||
const tal_t *ctx = talz(NULL, tal_t);
|
const tal_t *ctx = talz(NULL, tal_t);
|
||||||
|
u8 assocdata[32];
|
||||||
|
memset(assocdata, 'B', sizeof(assocdata));
|
||||||
|
|
||||||
secp256k1_ctx = secp256k1_context_create(
|
secp256k1_ctx = secp256k1_context_create(
|
||||||
SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN);
|
SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN);
|
||||||
@@ -56,7 +58,9 @@ int main(int argc, char **argv)
|
|||||||
struct onionpacket *res = create_onionpacket(ctx,
|
struct onionpacket *res = create_onionpacket(ctx,
|
||||||
path,
|
path,
|
||||||
hoppayloads,
|
hoppayloads,
|
||||||
sessionkey);
|
sessionkey,
|
||||||
|
assocdata,
|
||||||
|
sizeof(assocdata));
|
||||||
|
|
||||||
u8 *serialized = serialize_onionpacket(ctx, res);
|
u8 *serialized = serialize_onionpacket(ctx, res);
|
||||||
if (!serialized)
|
if (!serialized)
|
||||||
@@ -87,7 +91,8 @@ int main(int argc, char **argv)
|
|||||||
if (!msg)
|
if (!msg)
|
||||||
errx(1, "Error parsing message.");
|
errx(1, "Error parsing message.");
|
||||||
|
|
||||||
step = process_onionpacket(ctx, msg, &seckey);
|
step = process_onionpacket(ctx, msg, &seckey, assocdata,
|
||||||
|
sizeof(assocdata));
|
||||||
|
|
||||||
if (!step->next)
|
if (!step->next)
|
||||||
errx(1, "Error processing message.");
|
errx(1, "Error processing message.");
|
||||||
|
|||||||
Reference in New Issue
Block a user