mirror of
https://github.com/aljazceru/lightning.git
synced 2026-01-05 07:14:36 +01:00
hsm: Implement private key derivation needed for unilateral closes
Signed-off-by: Christian Decker <decker.christian@gmail.com>
This commit is contained in:
@@ -23,6 +23,7 @@ HSMD_COMMON_OBJS := \
|
||||
common/bip32.o \
|
||||
common/daemon_conn.o \
|
||||
common/debug.o \
|
||||
common/derive_basepoints.o \
|
||||
common/funding_tx.o \
|
||||
common/hash_u5.o \
|
||||
common/io_debug.o \
|
||||
|
||||
78
hsmd/hsm.c
78
hsmd/hsm.c
@@ -15,9 +15,11 @@
|
||||
#include <ccan/take/take.h>
|
||||
#include <common/daemon_conn.h>
|
||||
#include <common/debug.h>
|
||||
#include <common/derive_basepoints.h>
|
||||
#include <common/funding_tx.h>
|
||||
#include <common/hash_u5.h>
|
||||
#include <common/io_debug.h>
|
||||
#include <common/key_derive.h>
|
||||
#include <common/status.h>
|
||||
#include <common/type_to_string.h>
|
||||
#include <common/utils.h>
|
||||
@@ -344,16 +346,27 @@ static struct io_plan *handle_client(struct io_conn *conn,
|
||||
return io_close(conn);
|
||||
}
|
||||
|
||||
/**
|
||||
* hsm_peer_secret_base -- Derive the base secret seed for per-peer seeds
|
||||
*
|
||||
* This secret is shared by all channels/peers for the client. The
|
||||
* per-peer seeds will be generated from it by mixing in the
|
||||
* channel_id and the peer node_id.
|
||||
*/
|
||||
static void hsm_peer_secret_base(struct secret *peer_seed_base)
|
||||
{
|
||||
hkdf_sha256(peer_seed_base, sizeof(struct secret), NULL, 0,
|
||||
&secretstuff.hsm_secret, sizeof(secretstuff.hsm_secret),
|
||||
"peer seed", strlen("peer seed"));
|
||||
}
|
||||
|
||||
static void send_init_response(struct daemon_conn *master)
|
||||
{
|
||||
struct pubkey node_id;
|
||||
struct secret peer_seed;
|
||||
u8 *msg;
|
||||
|
||||
hkdf_sha256(&peer_seed, sizeof(peer_seed), NULL, 0,
|
||||
&secretstuff.hsm_secret,
|
||||
sizeof(secretstuff.hsm_secret),
|
||||
"peer seed", strlen("peer seed"));
|
||||
hsm_peer_secret_base(&peer_seed);
|
||||
node_key(NULL, &node_id);
|
||||
|
||||
msg = towire_hsm_init_reply(master, &node_id, &peer_seed,
|
||||
@@ -533,6 +546,55 @@ static void pass_client_hsmfd(struct daemon_conn *master, const u8 *msg)
|
||||
daemon_conn_send_fd(master, fds[1]);
|
||||
}
|
||||
|
||||
|
||||
static void derive_peer_seed(struct privkey *peer_seed, struct privkey *peer_seed_base,
|
||||
const struct pubkey *peer_id, const u64 channel_id)
|
||||
{
|
||||
u8 input[PUBKEY_DER_LEN + sizeof(channel_id)];
|
||||
char *info = "per-peer seed";
|
||||
pubkey_to_der(input, peer_id);
|
||||
memcpy(input + PUBKEY_DER_LEN, &channel_id, sizeof(channel_id));
|
||||
|
||||
hkdf_sha256(peer_seed, sizeof(*peer_seed),
|
||||
input, sizeof(input),
|
||||
peer_seed_base, sizeof(*peer_seed_base),
|
||||
info, strlen(info));
|
||||
}
|
||||
|
||||
static void hsm_unilateral_close_privkey(struct privkey *dst,
|
||||
struct unilateral_close_info *info)
|
||||
{
|
||||
struct privkey peer_seed, peer_seed_base;
|
||||
struct basepoints basepoints;
|
||||
struct secrets secrets;
|
||||
hsm_peer_secret_base(&peer_seed_base.secret);
|
||||
derive_peer_seed(&peer_seed, &peer_seed_base, &info->peer_id, info->channel_id);
|
||||
derive_basepoints(&peer_seed, NULL, &basepoints, &secrets, NULL);
|
||||
|
||||
derive_simple_privkey(&secrets.payment_basepoint_secret,
|
||||
&basepoints.payment, &info->commitment_point,
|
||||
dst);
|
||||
}
|
||||
|
||||
/**
|
||||
* hsm_key_for_utxo - generate the keypair matching the utxo
|
||||
*/
|
||||
static void hsm_key_for_utxo(struct privkey *privkey, struct pubkey *pubkey,
|
||||
const struct utxo *utxo)
|
||||
{
|
||||
if (utxo->close_info != NULL) {
|
||||
/* This is a their_unilateral_close/to-us output, so
|
||||
* we need to derive the secret the long way */
|
||||
status_trace("Unilateral close output, deriving secrets");
|
||||
hsm_unilateral_close_privkey(privkey, utxo->close_info);
|
||||
pubkey_from_privkey(privkey, pubkey);
|
||||
status_trace("Derived public key %s from unilateral close", type_to_string(trc, struct pubkey, pubkey));
|
||||
} else {
|
||||
/* Simple case: just get derive via HD-derivation */
|
||||
bitcoin_keypair(privkey, pubkey, utxo->keyindex);
|
||||
}
|
||||
}
|
||||
|
||||
/* Note that it's the main daemon that asks for the funding signature so it
|
||||
* can broadcast it. */
|
||||
static void sign_funding_tx(struct daemon_conn *master, const u8 *msg)
|
||||
@@ -575,7 +637,8 @@ static void sign_funding_tx(struct daemon_conn *master, const u8 *msg)
|
||||
u8 *subscript;
|
||||
secp256k1_ecdsa_signature sig;
|
||||
|
||||
bitcoin_keypair(&inprivkey, &inkey, in->keyindex);
|
||||
hsm_key_for_utxo(&inprivkey, &inkey, in);
|
||||
|
||||
if (in->is_p2sh)
|
||||
subscript = bitcoin_redeem_p2sh_p2wpkh(tmpctx, &inkey);
|
||||
else
|
||||
@@ -649,8 +712,9 @@ static void sign_withdrawal_tx(struct daemon_conn *master, const u8 *msg)
|
||||
u8 *subscript;
|
||||
secp256k1_ecdsa_signature sig;
|
||||
|
||||
bitcoin_keypair(&inprivkey, &inkey, in->keyindex);
|
||||
if (utxos[i]->is_p2sh)
|
||||
hsm_key_for_utxo(&inprivkey, &inkey, in);
|
||||
|
||||
if (in->is_p2sh || in->close_info != NULL)
|
||||
subscript = bitcoin_redeem_p2sh_p2wpkh(tmpctx, &inkey);
|
||||
else
|
||||
subscript = NULL;
|
||||
|
||||
Reference in New Issue
Block a user