|
|
@ -25,6 +25,9 @@ |
|
|
|
#include <ccan/read_write_all/read_write_all.h> |
|
|
|
#include <ccan/take/take.h> |
|
|
|
#include <ccan/tal/str/str.h> |
|
|
|
#if EXPERIMENTAL_FEATURES |
|
|
|
#include <common/bolt12_merkle.h> |
|
|
|
#endif |
|
|
|
#include <common/daemon_conn.h> |
|
|
|
#include <common/derive_basepoints.h> |
|
|
|
#include <common/hash_u5.h> |
|
|
@ -43,6 +46,7 @@ |
|
|
|
#include <hsmd/hsmd_wiregen.h> |
|
|
|
#include <inttypes.h> |
|
|
|
#include <secp256k1_ecdh.h> |
|
|
|
#include <secp256k1_schnorrsig.h> |
|
|
|
#include <sodium.h> |
|
|
|
#include <sys/socket.h> |
|
|
|
#include <sys/stat.h> |
|
|
@ -313,7 +317,7 @@ static void node_key(struct privkey *node_privkey, struct pubkey *node_id) |
|
|
|
/* If caller specifies NULL, they don't want the results. */ |
|
|
|
if (node_privkey == NULL) |
|
|
|
node_privkey = &unused_s; |
|
|
|
else if (node_id == NULL) |
|
|
|
if (node_id == NULL) |
|
|
|
node_id = &unused_k; |
|
|
|
|
|
|
|
/*~ So, there is apparently a 1 in 2^127 chance that a random value is
|
|
|
@ -343,6 +347,33 @@ static void node_key(struct privkey *node_privkey, struct pubkey *node_id) |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
#if EXPERIMENTAL_FEATURES |
|
|
|
/*~ This returns the secret and/or public x-only key for this node. */ |
|
|
|
static void node_schnorrkey(secp256k1_keypair *node_keypair, |
|
|
|
struct pubkey32 *node_id32) |
|
|
|
{ |
|
|
|
secp256k1_keypair unused_kp; |
|
|
|
struct privkey node_privkey; |
|
|
|
|
|
|
|
if (!node_keypair) |
|
|
|
node_keypair = &unused_kp; |
|
|
|
|
|
|
|
node_key(&node_privkey, NULL); |
|
|
|
if (secp256k1_keypair_create(secp256k1_ctx, node_keypair, |
|
|
|
node_privkey.secret.data) != 1) |
|
|
|
status_failed(STATUS_FAIL_INTERNAL_ERROR, |
|
|
|
"Failed to derive keypair"); |
|
|
|
|
|
|
|
if (node_id32) { |
|
|
|
if (secp256k1_keypair_xonly_pub(secp256k1_ctx, |
|
|
|
&node_id32->pubkey, |
|
|
|
NULL, node_keypair) != 1) |
|
|
|
status_failed(STATUS_FAIL_INTERNAL_ERROR, |
|
|
|
"Failed to derive xonly pub"); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
/*~ This secret is the basis for all per-channel secrets: the per-channel seeds
|
|
|
|
* will be generated by mixing in the dbid and the peer node_id. */ |
|
|
|
static void hsm_channel_secret_base(struct secret *channel_seed_base) |
|
|
@ -1790,6 +1821,36 @@ static struct io_plan *handle_sign_message(struct io_conn *conn, |
|
|
|
take(towire_hsmd_sign_message_reply(NULL, &rsig))); |
|
|
|
} |
|
|
|
|
|
|
|
#if EXPERIMENTAL_FEATURES |
|
|
|
/*~ lightningd asks us to sign a bolt12 (e.g. offer). */ |
|
|
|
static struct io_plan *handle_sign_bolt12(struct io_conn *conn, |
|
|
|
struct client *c, |
|
|
|
const u8 *msg_in) |
|
|
|
{ |
|
|
|
char *messagename, *fieldname; |
|
|
|
struct sha256 merkle, sha; |
|
|
|
struct bip340sig sig; |
|
|
|
secp256k1_keypair node_kp; |
|
|
|
|
|
|
|
if (!fromwire_hsmd_sign_bolt12(tmpctx, msg_in, |
|
|
|
&messagename, &fieldname, &merkle)) |
|
|
|
return bad_req(conn, c, msg_in); |
|
|
|
|
|
|
|
sighash_from_merkle(messagename, fieldname, &merkle, &sha); |
|
|
|
|
|
|
|
node_schnorrkey(&node_kp, NULL); |
|
|
|
if (!secp256k1_schnorrsig_sign(secp256k1_ctx, sig.u8, |
|
|
|
sha.u.u8, |
|
|
|
&node_kp, |
|
|
|
NULL, NULL)) { |
|
|
|
return bad_req_fmt(conn, c, msg_in, "Failed to sign bolt12"); |
|
|
|
} |
|
|
|
|
|
|
|
return req_reply(conn, c, |
|
|
|
take(towire_hsmd_sign_bolt12_reply(NULL, &sig))); |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
#if DEVELOPER |
|
|
|
static struct io_plan *handle_memleak(struct io_conn *conn, |
|
|
|
struct client *c, |
|
|
@ -1871,6 +1932,7 @@ static bool check_client_capabilities(struct client *client, |
|
|
|
case WIRE_HSMD_DEV_MEMLEAK: |
|
|
|
case WIRE_HSMD_SIGN_MESSAGE: |
|
|
|
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY: |
|
|
|
case WIRE_HSMD_SIGN_BOLT12: |
|
|
|
return (client->capabilities & HSM_CAP_MASTER) != 0; |
|
|
|
|
|
|
|
/*~ These are messages sent by the HSM so we should never receive them. */ |
|
|
@ -1893,6 +1955,7 @@ static bool check_client_capabilities(struct client *client, |
|
|
|
case WIRE_HSMD_DEV_MEMLEAK_REPLY: |
|
|
|
case WIRE_HSMD_SIGN_MESSAGE_REPLY: |
|
|
|
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY_REPLY: |
|
|
|
case WIRE_HSMD_SIGN_BOLT12_REPLY: |
|
|
|
break; |
|
|
|
} |
|
|
|
return false; |
|
|
@ -1975,6 +2038,13 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) |
|
|
|
|
|
|
|
case WIRE_HSMD_SIGN_MESSAGE: |
|
|
|
return handle_sign_message(conn, c, c->msg_in); |
|
|
|
|
|
|
|
case WIRE_HSMD_SIGN_BOLT12: |
|
|
|
#if EXPERIMENTAL_FEATURES |
|
|
|
return handle_sign_bolt12(conn, c, c->msg_in); |
|
|
|
#else |
|
|
|
break; |
|
|
|
#endif |
|
|
|
#if DEVELOPER |
|
|
|
case WIRE_HSMD_DEV_MEMLEAK: |
|
|
|
return handle_memleak(conn, c, c->msg_in); |
|
|
@ -1998,6 +2068,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) |
|
|
|
case WIRE_HSMD_DEV_MEMLEAK_REPLY: |
|
|
|
case WIRE_HSMD_SIGN_MESSAGE_REPLY: |
|
|
|
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY_REPLY: |
|
|
|
case WIRE_HSMD_SIGN_BOLT12_REPLY: |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|