hsmd: take the passphrase raw, not the derived secret.

In preparation for BIP-39, we need to hand the passphrase (if any) to HSMD.

So we extend the hsmd wire protocol to allow that.
This commit is contained in:
Sangbida Chaudhuri
2025-10-24 13:57:43 +10:30
committed by Rusty Russell
parent 3da0f16f14
commit e3fe739f64
7 changed files with 47 additions and 24 deletions

View File

@@ -461,6 +461,7 @@ static struct io_plan *init_hsm(struct io_conn *conn,
struct bip32_key_version bip32_key_version;
u32 minversion, maxversion;
const u32 our_minversion = 4, our_maxversion = 6;
struct tlv_hsmd_init_tlvs *tlvs;
/* This must be lightningd. */
assert(is_lightningd(c));
@@ -475,7 +476,7 @@ static struct io_plan *init_hsm(struct io_conn *conn,
&dev_force_bip32_seed,
&dev_force_channel_secrets,
&dev_force_channel_secrets_shaseed,
&minversion, &maxversion))
&minversion, &maxversion, &tlvs))
return bad_req(conn, c, msg_in);
/*~ Usually we don't worry about API breakage between internal daemons,
@@ -487,6 +488,25 @@ static struct io_plan *init_hsm(struct io_conn *conn,
minversion, maxversion,
our_minversion, our_maxversion);
/*~ We used to have lightningd hand us the encryption key derived from
* the passphrase which was used to encrypt the `hsm_secret` file. Then
* Rusty gave me the thankless task of introducing BIP-39 mnemonics. I
* think this is some kind of obscure CLN hazing ritual? Anyway, the
* passphrase needs to be *appended* to the mnemonic, so the HSM needs
* the raw passphrase. To avoid a compatibility break, I put it inside
* the TLV, and left the old "hsm_encryption_key" field in place, even
* though we override it here for the old-style non-BIP39 hsm_secret. */
if (tlvs->hsm_passphrase) {
const char *hsm_passphrase = (const char *)tlvs->hsm_passphrase;
const char *err_msg;
hsm_encryption_key = tal(NULL, struct secret);
if (hsm_secret_encryption_key_with_exitcode(hsm_passphrase, hsm_encryption_key, &err_msg) != 0)
return bad_req_fmt(conn, c, msg_in,
"Bad passphrase: %s", err_msg);
}
tal_free(tlvs);
/*~ The memory is actually copied in towire(), so lock the `hsm_secret`
* encryption key (new) memory again here. */
if (hsm_encryption_key && sodium_mlock(hsm_encryption_key,

View File

@@ -29,6 +29,9 @@ msgdata,hsmd_init,dev_force_channel_secrets,?secrets,
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,
msgdata,hsmd_init,tlvs,hsmd_init_tlvs,
tlvtype,hsmd_init_tlvs,hsm_passphrase,1
tlvdata,hsmd_init_tlvs,hsm_passphrase,passphrase,wirestring,
#include <common/bip32.h>
# Sorry: I should have put version in v2 :(
1 # Clients should not give a bad request but not the HSM's decision to crash.
29 msgdata,hsmd_init,hsm_wire_max_version,u32,
30 #include <common/bip32.h> msgdata,hsmd_init,tlvs,hsmd_init_tlvs,
31 # Sorry: I should have put version in v2 :( tlvtype,hsmd_init_tlvs,hsm_passphrase,1
32 tlvdata,hsmd_init_tlvs,hsm_passphrase,passphrase,wirestring,
33 #include <common/bip32.h>
34 # Sorry: I should have put version in v2 :(
35 msgtype,hsmd_init_reply_v4,114
36 # This gets upgraded when the wire protocol changes in incompatible
37 # ways: