mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
hsmd: code to sign a bolt12 merkle root.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
f315f1c63f
commit
86176e8d0a
@ -42,6 +42,10 @@ HSMD_COMMON_OBJS := \
|
|||||||
common/utxo.o \
|
common/utxo.o \
|
||||||
common/version.o
|
common/version.o
|
||||||
|
|
||||||
|
ifeq ($(EXPERIMENTAL_FEATURES),1)
|
||||||
|
HSMD_COMMON_OBJS += common/bolt12_merkle.o
|
||||||
|
endif
|
||||||
|
|
||||||
lightningd/lightning_hsmd: $(HSMD_OBJS) $(HSMD_COMMON_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS)
|
lightningd/lightning_hsmd: $(HSMD_OBJS) $(HSMD_COMMON_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS)
|
||||||
|
|
||||||
-include hsmd/test/Makefile
|
-include hsmd/test/Makefile
|
||||||
|
73
hsmd/hsmd.c
73
hsmd/hsmd.c
@ -25,6 +25,9 @@
|
|||||||
#include <ccan/read_write_all/read_write_all.h>
|
#include <ccan/read_write_all/read_write_all.h>
|
||||||
#include <ccan/take/take.h>
|
#include <ccan/take/take.h>
|
||||||
#include <ccan/tal/str/str.h>
|
#include <ccan/tal/str/str.h>
|
||||||
|
#if EXPERIMENTAL_FEATURES
|
||||||
|
#include <common/bolt12_merkle.h>
|
||||||
|
#endif
|
||||||
#include <common/daemon_conn.h>
|
#include <common/daemon_conn.h>
|
||||||
#include <common/derive_basepoints.h>
|
#include <common/derive_basepoints.h>
|
||||||
#include <common/hash_u5.h>
|
#include <common/hash_u5.h>
|
||||||
@ -43,6 +46,7 @@
|
|||||||
#include <hsmd/hsmd_wiregen.h>
|
#include <hsmd/hsmd_wiregen.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <secp256k1_ecdh.h>
|
#include <secp256k1_ecdh.h>
|
||||||
|
#include <secp256k1_schnorrsig.h>
|
||||||
#include <sodium.h>
|
#include <sodium.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/stat.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 caller specifies NULL, they don't want the results. */
|
||||||
if (node_privkey == NULL)
|
if (node_privkey == NULL)
|
||||||
node_privkey = &unused_s;
|
node_privkey = &unused_s;
|
||||||
else if (node_id == NULL)
|
if (node_id == NULL)
|
||||||
node_id = &unused_k;
|
node_id = &unused_k;
|
||||||
|
|
||||||
/*~ So, there is apparently a 1 in 2^127 chance that a random value is
|
/*~ 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
|
#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
|
/*~ 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. */
|
* will be generated by mixing in the dbid and the peer node_id. */
|
||||||
static void hsm_channel_secret_base(struct secret *channel_seed_base)
|
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)));
|
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
|
#if DEVELOPER
|
||||||
static struct io_plan *handle_memleak(struct io_conn *conn,
|
static struct io_plan *handle_memleak(struct io_conn *conn,
|
||||||
struct client *c,
|
struct client *c,
|
||||||
@ -1871,6 +1932,7 @@ static bool check_client_capabilities(struct client *client,
|
|||||||
case WIRE_HSMD_DEV_MEMLEAK:
|
case WIRE_HSMD_DEV_MEMLEAK:
|
||||||
case WIRE_HSMD_SIGN_MESSAGE:
|
case WIRE_HSMD_SIGN_MESSAGE:
|
||||||
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY:
|
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY:
|
||||||
|
case WIRE_HSMD_SIGN_BOLT12:
|
||||||
return (client->capabilities & HSM_CAP_MASTER) != 0;
|
return (client->capabilities & HSM_CAP_MASTER) != 0;
|
||||||
|
|
||||||
/*~ These are messages sent by the HSM so we should never receive them. */
|
/*~ 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_DEV_MEMLEAK_REPLY:
|
||||||
case WIRE_HSMD_SIGN_MESSAGE_REPLY:
|
case WIRE_HSMD_SIGN_MESSAGE_REPLY:
|
||||||
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY_REPLY:
|
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY_REPLY:
|
||||||
|
case WIRE_HSMD_SIGN_BOLT12_REPLY:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -1975,6 +2038,13 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c)
|
|||||||
|
|
||||||
case WIRE_HSMD_SIGN_MESSAGE:
|
case WIRE_HSMD_SIGN_MESSAGE:
|
||||||
return handle_sign_message(conn, c, c->msg_in);
|
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
|
#if DEVELOPER
|
||||||
case WIRE_HSMD_DEV_MEMLEAK:
|
case WIRE_HSMD_DEV_MEMLEAK:
|
||||||
return handle_memleak(conn, c, c->msg_in);
|
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_DEV_MEMLEAK_REPLY:
|
||||||
case WIRE_HSMD_SIGN_MESSAGE_REPLY:
|
case WIRE_HSMD_SIGN_MESSAGE_REPLY:
|
||||||
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY_REPLY:
|
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY_REPLY:
|
||||||
|
case WIRE_HSMD_SIGN_BOLT12_REPLY:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,3 +198,13 @@ msgdata,hsmd_get_output_scriptpubkey,commitment_point,?pubkey,
|
|||||||
msgtype,hsmd_get_output_scriptpubkey_reply,124
|
msgtype,hsmd_get_output_scriptpubkey_reply,124
|
||||||
msgdata,hsmd_get_output_scriptpubkey_reply,script_len,u16,
|
msgdata,hsmd_get_output_scriptpubkey_reply,script_len,u16,
|
||||||
msgdata,hsmd_get_output_scriptpubkey_reply,script,u8,script_len
|
msgdata,hsmd_get_output_scriptpubkey_reply,script,u8,script_len
|
||||||
|
|
||||||
|
# Sign a bolt12-style merkle hash
|
||||||
|
msgtype,hsmd_sign_bolt12,25
|
||||||
|
msgdata,hsmd_sign_bolt12,messagename,wirestring,
|
||||||
|
msgdata,hsmd_sign_bolt12,fieldname,wirestring,
|
||||||
|
msgdata,hsmd_sign_bolt12,merkleroot,sha256,
|
||||||
|
|
||||||
|
msgtype,hsmd_sign_bolt12_reply,125
|
||||||
|
msgdata,hsmd_sign_bolt12_reply,sig,bip340sig,
|
||||||
|
|
||||||
|
|
53
hsmd/hsmd_wiregen.c
generated
53
hsmd/hsmd_wiregen.c
generated
@ -60,6 +60,8 @@ const char *hsmd_wire_name(int e)
|
|||||||
case WIRE_HSMD_SIGN_MESSAGE_REPLY: return "WIRE_HSMD_SIGN_MESSAGE_REPLY";
|
case WIRE_HSMD_SIGN_MESSAGE_REPLY: return "WIRE_HSMD_SIGN_MESSAGE_REPLY";
|
||||||
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY: return "WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY";
|
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY: return "WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY";
|
||||||
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY_REPLY: return "WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY_REPLY";
|
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY_REPLY: return "WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY_REPLY";
|
||||||
|
case WIRE_HSMD_SIGN_BOLT12: return "WIRE_HSMD_SIGN_BOLT12";
|
||||||
|
case WIRE_HSMD_SIGN_BOLT12_REPLY: return "WIRE_HSMD_SIGN_BOLT12_REPLY";
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(invalidbuf, sizeof(invalidbuf), "INVALID %i", e);
|
snprintf(invalidbuf, sizeof(invalidbuf), "INVALID %i", e);
|
||||||
@ -108,6 +110,8 @@ bool hsmd_wire_is_defined(u16 type)
|
|||||||
case WIRE_HSMD_SIGN_MESSAGE_REPLY:;
|
case WIRE_HSMD_SIGN_MESSAGE_REPLY:;
|
||||||
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY:;
|
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY:;
|
||||||
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY_REPLY:;
|
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY_REPLY:;
|
||||||
|
case WIRE_HSMD_SIGN_BOLT12:;
|
||||||
|
case WIRE_HSMD_SIGN_BOLT12_REPLY:;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -1214,4 +1218,51 @@ bool fromwire_hsmd_get_output_scriptpubkey_reply(const tal_t *ctx, const void *p
|
|||||||
fromwire_u8_array(&cursor, &plen, *script, script_len);
|
fromwire_u8_array(&cursor, &plen, *script, script_len);
|
||||||
return cursor != NULL;
|
return cursor != NULL;
|
||||||
}
|
}
|
||||||
// SHA256STAMP:02b3951c8bdb27997f5a30ebcf2e174cb99d6089d889b94da925fd674fca653f
|
|
||||||
|
/* WIRE: HSMD_SIGN_BOLT12 */
|
||||||
|
/* Sign a bolt12-style merkle hash */
|
||||||
|
u8 *towire_hsmd_sign_bolt12(const tal_t *ctx, const wirestring *messagename, const wirestring *fieldname, const struct sha256 *merkleroot)
|
||||||
|
{
|
||||||
|
u8 *p = tal_arr(ctx, u8, 0);
|
||||||
|
|
||||||
|
towire_u16(&p, WIRE_HSMD_SIGN_BOLT12);
|
||||||
|
towire_wirestring(&p, messagename);
|
||||||
|
towire_wirestring(&p, fieldname);
|
||||||
|
towire_sha256(&p, merkleroot);
|
||||||
|
|
||||||
|
return memcheck(p, tal_count(p));
|
||||||
|
}
|
||||||
|
bool fromwire_hsmd_sign_bolt12(const tal_t *ctx, const void *p, wirestring **messagename, wirestring **fieldname, struct sha256 *merkleroot)
|
||||||
|
{
|
||||||
|
const u8 *cursor = p;
|
||||||
|
size_t plen = tal_count(p);
|
||||||
|
|
||||||
|
if (fromwire_u16(&cursor, &plen) != WIRE_HSMD_SIGN_BOLT12)
|
||||||
|
return false;
|
||||||
|
*messagename = fromwire_wirestring(ctx, &cursor, &plen);
|
||||||
|
*fieldname = fromwire_wirestring(ctx, &cursor, &plen);
|
||||||
|
fromwire_sha256(&cursor, &plen, merkleroot);
|
||||||
|
return cursor != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WIRE: HSMD_SIGN_BOLT12_REPLY */
|
||||||
|
u8 *towire_hsmd_sign_bolt12_reply(const tal_t *ctx, const struct bip340sig *sig)
|
||||||
|
{
|
||||||
|
u8 *p = tal_arr(ctx, u8, 0);
|
||||||
|
|
||||||
|
towire_u16(&p, WIRE_HSMD_SIGN_BOLT12_REPLY);
|
||||||
|
towire_bip340sig(&p, sig);
|
||||||
|
|
||||||
|
return memcheck(p, tal_count(p));
|
||||||
|
}
|
||||||
|
bool fromwire_hsmd_sign_bolt12_reply(const void *p, struct bip340sig *sig)
|
||||||
|
{
|
||||||
|
const u8 *cursor = p;
|
||||||
|
size_t plen = tal_count(p);
|
||||||
|
|
||||||
|
if (fromwire_u16(&cursor, &plen) != WIRE_HSMD_SIGN_BOLT12_REPLY)
|
||||||
|
return false;
|
||||||
|
fromwire_bip340sig(&cursor, &plen, sig);
|
||||||
|
return cursor != NULL;
|
||||||
|
}
|
||||||
|
// SHA256STAMP:cb033b99e13d9bdd06582a34132ba7cd311f4cf074298da1addcdad06b3fdf8f
|
||||||
|
14
hsmd/hsmd_wiregen.h
generated
14
hsmd/hsmd_wiregen.h
generated
@ -76,6 +76,9 @@ enum hsmd_wire {
|
|||||||
/* lightningd needs to get a scriptPubkey for a utxo with closeinfo */
|
/* lightningd needs to get a scriptPubkey for a utxo with closeinfo */
|
||||||
WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY = 24,
|
WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY = 24,
|
||||||
WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY_REPLY = 124,
|
WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY_REPLY = 124,
|
||||||
|
/* Sign a bolt12-style merkle hash */
|
||||||
|
WIRE_HSMD_SIGN_BOLT12 = 25,
|
||||||
|
WIRE_HSMD_SIGN_BOLT12_REPLY = 125,
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *hsmd_wire_name(int e);
|
const char *hsmd_wire_name(int e);
|
||||||
@ -269,6 +272,15 @@ bool fromwire_hsmd_get_output_scriptpubkey(const tal_t *ctx, const void *p, u64
|
|||||||
u8 *towire_hsmd_get_output_scriptpubkey_reply(const tal_t *ctx, const u8 *script);
|
u8 *towire_hsmd_get_output_scriptpubkey_reply(const tal_t *ctx, const u8 *script);
|
||||||
bool fromwire_hsmd_get_output_scriptpubkey_reply(const tal_t *ctx, const void *p, u8 **script);
|
bool fromwire_hsmd_get_output_scriptpubkey_reply(const tal_t *ctx, const void *p, u8 **script);
|
||||||
|
|
||||||
|
/* WIRE: HSMD_SIGN_BOLT12 */
|
||||||
|
/* Sign a bolt12-style merkle hash */
|
||||||
|
u8 *towire_hsmd_sign_bolt12(const tal_t *ctx, const wirestring *messagename, const wirestring *fieldname, const struct sha256 *merkleroot);
|
||||||
|
bool fromwire_hsmd_sign_bolt12(const tal_t *ctx, const void *p, wirestring **messagename, wirestring **fieldname, struct sha256 *merkleroot);
|
||||||
|
|
||||||
|
/* WIRE: HSMD_SIGN_BOLT12_REPLY */
|
||||||
|
u8 *towire_hsmd_sign_bolt12_reply(const tal_t *ctx, const struct bip340sig *sig);
|
||||||
|
bool fromwire_hsmd_sign_bolt12_reply(const void *p, struct bip340sig *sig);
|
||||||
|
|
||||||
|
|
||||||
#endif /* LIGHTNING_HSMD_HSMD_WIREGEN_H */
|
#endif /* LIGHTNING_HSMD_HSMD_WIREGEN_H */
|
||||||
// SHA256STAMP:02b3951c8bdb27997f5a30ebcf2e174cb99d6089d889b94da925fd674fca653f
|
// SHA256STAMP:cb033b99e13d9bdd06582a34132ba7cd311f4cf074298da1addcdad06b3fdf8f
|
||||||
|
Loading…
Reference in New Issue
Block a user