hsmd: introduce a simple API versioning scheme.

With the rise of external HSMs like VLS, this is no longer an
internal-only API.  Fortunately, it doesn't change very fast so
maintenance should not be a huge burden.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2022-10-17 11:04:08 +10:30
parent e00857827f
commit fee9a7ce04
5 changed files with 29 additions and 2 deletions

View File

@@ -98,6 +98,7 @@ COMMON_HEADERS_NOGEN := $(COMMON_SRC_NOGEN:.c=.h) \
common/ecdh.h \ common/ecdh.h \
common/errcode.h \ common/errcode.h \
common/gossip_constants.h \ common/gossip_constants.h \
common/hsm_version.h \
common/htlc.h \ common/htlc.h \
common/json_command.h \ common/json_command.h \
common/jsonrpc_errors.h \ common/jsonrpc_errors.h \

9
common/hsm_version.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef LIGHTNING_COMMON_HSM_VERSION_H
#define LIGHTNING_COMMON_HSM_VERSION_H
#include "config.h"
/* We give a maximum and minimum compatibility version to HSM, to allow
* some API adaptation. */
#define HSM_MIN_VERSION 1
#define HSM_MAX_VERSION 1
#endif /* LIGHTNING_COMMON_HSM_VERSION_H */

View File

@@ -443,6 +443,8 @@ static struct io_plan *init_hsm(struct io_conn *conn,
struct sha256 *shaseed; struct sha256 *shaseed;
struct secret *hsm_encryption_key; struct secret *hsm_encryption_key;
struct bip32_key_version bip32_key_version; struct bip32_key_version bip32_key_version;
u32 minversion, maxversion;
const u32 our_minversion = 1, our_maxversion = 1;
/* This must be lightningd. */ /* This must be lightningd. */
assert(is_lightningd(c)); assert(is_lightningd(c));
@@ -452,9 +454,19 @@ static struct io_plan *init_hsm(struct io_conn *conn,
* an extension of the simple comma-separated format output by the * an extension of the simple comma-separated format output by the
* BOLT tools/extract-formats.py tool. */ * BOLT tools/extract-formats.py tool. */
if (!fromwire_hsmd_init(NULL, msg_in, &bip32_key_version, &chainparams, if (!fromwire_hsmd_init(NULL, msg_in, &bip32_key_version, &chainparams,
&hsm_encryption_key, &privkey, &seed, &secrets, &shaseed)) &hsm_encryption_key, &privkey, &seed, &secrets, &shaseed,
&minversion, &maxversion))
return bad_req(conn, c, msg_in); return bad_req(conn, c, msg_in);
/*~ Usually we don't worry about API breakage between internal daemons,
* but there are other implementations of the HSM daemon now, so we
* do at least the simplest, clearest thing. */
if (our_minversion > maxversion || our_maxversion < minversion)
return bad_req_fmt(conn, c, msg_in,
"Version %u-%u not valid: we need %u-%u",
minversion, maxversion,
our_minversion, our_maxversion);
/*~ The memory is actually copied in towire(), so lock the `hsm_secret` /*~ The memory is actually copied in towire(), so lock the `hsm_secret`
* encryption key (new) memory again here. */ * encryption key (new) memory again here. */
if (hsm_encryption_key && sodium_mlock(hsm_encryption_key, if (hsm_encryption_key && sodium_mlock(hsm_encryption_key,

View File

@@ -15,6 +15,8 @@ msgdata,hsmd_init,dev_force_privkey,?privkey,
msgdata,hsmd_init,dev_force_bip32_seed,?secret, msgdata,hsmd_init,dev_force_bip32_seed,?secret,
msgdata,hsmd_init,dev_force_channel_secrets,?secrets, msgdata,hsmd_init,dev_force_channel_secrets,?secrets,
msgdata,hsmd_init,dev_force_channel_secrets_shaseed,?sha256, msgdata,hsmd_init,dev_force_channel_secrets_shaseed,?sha256,
msgdata,hsmd_init,hsm_wire_min_version,u32,
msgdata,hsmd_init,hsm_wire_max_version,u32,
#include <common/bip32.h> #include <common/bip32.h>
msgtype,hsmd_init_reply,111 msgtype,hsmd_init_reply,111
1 # Clients should not give a bad request but not the HSM's decision to crash.
15 msgdata,hsmd_init,dev_force_channel_secrets,?secrets,
16 msgdata,hsmd_init,dev_force_channel_secrets_shaseed,?sha256,
17 #include <common/bip32.h> msgdata,hsmd_init,hsm_wire_min_version,u32,
18 msgdata,hsmd_init,hsm_wire_max_version,u32,
19 #include <common/bip32.h>
20 msgtype,hsmd_init_reply,111
21 msgdata,hsmd_init_reply,node_id,node_id,
22 msgdata,hsmd_init_reply,bip32,ext_key,

View File

@@ -4,6 +4,7 @@
#include <common/ecdh.h> #include <common/ecdh.h>
#include <common/errcode.h> #include <common/errcode.h>
#include <common/hsm_encryption.h> #include <common/hsm_encryption.h>
#include <common/hsm_version.h>
#include <common/json_command.h> #include <common/json_command.h>
#include <common/json_param.h> #include <common/json_param.h>
#include <common/jsonrpc_errors.h> #include <common/jsonrpc_errors.h>
@@ -109,7 +110,9 @@ struct ext_key *hsm_init(struct lightningd *ld)
IFDEV(ld->dev_force_privkey, NULL), IFDEV(ld->dev_force_privkey, NULL),
IFDEV(ld->dev_force_bip32_seed, NULL), IFDEV(ld->dev_force_bip32_seed, NULL),
IFDEV(ld->dev_force_channel_secrets, NULL), IFDEV(ld->dev_force_channel_secrets, NULL),
IFDEV(ld->dev_force_channel_secrets_shaseed, NULL)))) IFDEV(ld->dev_force_channel_secrets_shaseed, NULL),
HSM_MIN_VERSION,
HSM_MAX_VERSION)))
err(EXITCODE_HSM_GENERIC_ERROR, "Writing init msg to hsm"); err(EXITCODE_HSM_GENERIC_ERROR, "Writing init msg to hsm");
bip32_base = tal(ld, struct ext_key); bip32_base = tal(ld, struct ext_key);