diff --git a/daemon/peer.c b/daemon/peer.c index 941246f58..c72073f57 100644 --- a/daemon/peer.c +++ b/daemon/peer.c @@ -911,11 +911,18 @@ static void their_htlc_added(struct peer *peer, struct htlc *htlc, //FIXME: dirty trick to retrieve unexported state memcpy(&pk, peer->dstate->secret, sizeof(pk)); + packet = parse_onionpacket(peer, htlc->routing, tal_count(htlc->routing)); - if (packet) - step = process_onionpacket(packet, packet, &pk, htlc->rhash.u.u8, - sizeof(htlc->rhash)); + if (packet) { + u8 shared_secret[32]; + + if (onion_shared_secret(shared_secret, packet, &pk)) + step = process_onionpacket(packet, packet, + shared_secret, + htlc->rhash.u.u8, + sizeof(htlc->rhash)); + } if (!step) { log_unusual(peer->log, "Bad onion, failing HTLC %"PRIu64, diff --git a/daemon/sphinx.c b/daemon/sphinx.c index 216429702..3d1485659 100644 --- a/daemon/sphinx.c +++ b/daemon/sphinx.c @@ -247,6 +247,15 @@ static bool create_shared_secret( return true; } +bool onion_shared_secret( + u8 *secret, + const struct onionpacket *packet, + const struct privkey *privkey) +{ + return create_shared_secret(secret, &packet->ephemeralkey, + privkey->secret); +} + void pubkey_hash160( u8 *dst, const struct pubkey *pubkey) @@ -267,7 +276,8 @@ void pubkey_hash160( memcpy(dst, r.u.u8, sizeof(r)); } -static void generate_key_set(u8 secret[SHARED_SECRET_SIZE], struct keyset *keys) +static void generate_key_set(const u8 secret[SHARED_SECRET_SIZE], + struct keyset *keys) { generate_key(keys->rho, "rho", 3, secret); generate_key(keys->pi, "pi", 2, secret); @@ -417,13 +427,12 @@ struct onionpacket *create_onionpacket( struct route_step *process_onionpacket( const tal_t *ctx, const struct onionpacket *msg, - struct privkey *hop_privkey, + const u8 *shared_secret, const u8 *assocdata, const size_t assocdatalen ) { struct route_step *step = talz(ctx, struct route_step); - u8 secret[SHARED_SECRET_SIZE]; u8 hmac[20]; struct keyset keys; u8 paddedhoppayloads[TOTAL_HOP_PAYLOAD_SIZE + HOP_PAYLOAD_SIZE]; @@ -434,8 +443,7 @@ struct route_step *process_onionpacket( step->next = talz(step, struct onionpacket); step->next->version = msg->version; - create_shared_secret(secret, &msg->ephemeralkey, hop_privkey->secret); - generate_key_set(secret, &keys); + generate_key_set(shared_secret, &keys); compute_packet_hmac(msg, assocdata, assocdatalen, keys.mu, hmac); @@ -461,7 +469,7 @@ struct route_step *process_onionpacket( memcpy(&step->next->hoppayloads, paddedhoppayloads + HOP_PAYLOAD_SIZE, TOTAL_HOP_PAYLOAD_SIZE); - compute_blinding_factor(&msg->ephemeralkey, secret, blind); + compute_blinding_factor(&msg->ephemeralkey, shared_secret, blind); if (!blind_group_element(&step->next->ephemeralkey, &msg->ephemeralkey, blind)) return tal_free(step); memcpy(&step->next->nexthop, paddedheader, SECURITY_PARAMETER); diff --git a/daemon/sphinx.h b/daemon/sphinx.h index 65813f3bf..ab373c079 100644 --- a/daemon/sphinx.h +++ b/daemon/sphinx.h @@ -69,13 +69,25 @@ struct onionpacket *create_onionpacket( const size_t assocdatalen ); +/** + * onion_shared_secret - calculate ECDH shared secret between nodes. + * + * @secret: the shared secret (32 bytes long) + * @pubkey: the public key of the other node + * @privkey: the private key of this node (32 bytes long) + */ +bool onion_shared_secret( + u8 *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 - * @hop_privkey: the processing node's private key to decrypt the packet + * @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 @@ -83,7 +95,7 @@ struct onionpacket *create_onionpacket( struct route_step *process_onionpacket( const tal_t * ctx, const struct onionpacket *packet, - struct privkey *hop_privkey, + const u8 *shared_secret, const u8 *assocdata, const size_t assocdatalen ); diff --git a/test/test_sphinx.c b/test/test_sphinx.c index 8ae231647..de3016af2 100644 --- a/test/test_sphinx.c +++ b/test/test_sphinx.c @@ -78,6 +78,7 @@ int main(int argc, char **argv) u8 serialized[TOTAL_PACKET_SIZE]; char hextemp[2 * sizeof(serialized) + 1]; memset(hextemp, 0, sizeof(hextemp)); + u8 shared_secret[32]; if (argc != 2) opt_usage_exit_fail("Expect a privkey with --decode"); @@ -91,7 +92,10 @@ int main(int argc, char **argv) if (!msg) errx(1, "Error parsing message."); - step = process_onionpacket(ctx, msg, &seckey, assocdata, + if (!onion_shared_secret(shared_secret, msg, &seckey)) + errx(1, "Error creating shared secret."); + + step = process_onionpacket(ctx, msg, shared_secret, assocdata, sizeof(assocdata)); if (!step->next)