Skip to content

Commit 13ae5fd

Browse files
sangbidarustyrussell
authored andcommitted
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.
1 parent d375ced commit 13ae5fd

File tree

8 files changed

+49
-30
lines changed

8 files changed

+49
-30
lines changed

hsmd/hsmd.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,7 @@ static struct io_plan *init_hsm(struct io_conn *conn,
461461
struct bip32_key_version bip32_key_version;
462462
u32 minversion, maxversion;
463463
const u32 our_minversion = 4, our_maxversion = 6;
464+
struct tlv_hsmd_init_tlvs *tlvs;
464465

465466
/* This must be lightningd. */
466467
assert(is_lightningd(c));
@@ -475,7 +476,7 @@ static struct io_plan *init_hsm(struct io_conn *conn,
475476
&dev_force_bip32_seed,
476477
&dev_force_channel_secrets,
477478
&dev_force_channel_secrets_shaseed,
478-
&minversion, &maxversion))
479+
&minversion, &maxversion, &tlvs))
479480
return bad_req(conn, c, msg_in);
480481

481482
/*~ 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,
487488
minversion, maxversion,
488489
our_minversion, our_maxversion);
489490

491+
/*~ We used to have lightningd hand us the encryption key derived from
492+
* the passphrase which was used to encrypt the `hsm_secret` file. Then
493+
* Rusty gave me the thankless task of introducing BIP-39 mnemonics. I
494+
* think this is some kind of obscure CLN hazing ritual? Anyway, the
495+
* passphrase needs to be *appended* to the mnemonic, so the HSM needs
496+
* the raw passphrase. To avoid a compatibility break, I put it inside
497+
* the TLV, and left the old "hsm_encryption_key" field in place, even
498+
* though we override it here for the old-style non-BIP39 hsm_secret. */
499+
if (tlvs->hsm_passphrase) {
500+
const char *hsm_passphrase = (const char *)tlvs->hsm_passphrase;
501+
const char *err_msg;
502+
503+
hsm_encryption_key = tal(NULL, struct secret);
504+
if (hsm_secret_encryption_key_with_exitcode(hsm_passphrase, hsm_encryption_key, &err_msg) != 0)
505+
return bad_req_fmt(conn, c, msg_in,
506+
"Bad passphrase: %s", err_msg);
507+
}
508+
tal_free(tlvs);
509+
490510
/*~ The memory is actually copied in towire(), so lock the `hsm_secret`
491511
* encryption key (new) memory again here. */
492512
if (hsm_encryption_key && sodium_mlock(hsm_encryption_key,

hsmd/hsmd_wire.csv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ msgdata,hsmd_init,dev_force_channel_secrets,?secrets,
2929
msgdata,hsmd_init,dev_force_channel_secrets_shaseed,?sha256,
3030
msgdata,hsmd_init,hsm_wire_min_version,u32,
3131
msgdata,hsmd_init,hsm_wire_max_version,u32,
32+
msgdata,hsmd_init,tlvs,hsmd_init_tlvs,
33+
tlvtype,hsmd_init_tlvs,hsm_passphrase,1
34+
tlvdata,hsmd_init_tlvs,hsm_passphrase,passphrase,wirestring,
3235

3336
#include <common/bip32.h>
3437
# Sorry: I should have put version in v2 :(

lightningd/hsm_control.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ struct ext_key *hsm_init(struct lightningd *ld)
103103
/* If hsm_secret is encrypted and the --encrypted-hsm startup option is
104104
* not passed, don't let hsmd use the first 32 bytes of the cypher as the
105105
* actual secret. */
106-
if (!ld->config.keypass) {
106+
if (!ld->hsm_passphrase) {
107107
if (is_hsm_secret_encrypted("hsm_secret") == 1)
108108
errx(EXITCODE_HSM_ERROR_IS_ENCRYPT, "hsm_secret is encrypted, you need to pass the "
109109
"--encrypted-hsm startup option.");
@@ -127,16 +127,24 @@ struct ext_key *hsm_init(struct lightningd *ld)
127127
err(EXITCODE_HSM_GENERIC_ERROR, "Writing preinit msg to hsm");
128128
}
129129

130+
/* Create TLV for passphrase if needed */
131+
struct tlv_hsmd_init_tlvs *tlv = NULL;
132+
if (ld->hsm_passphrase) {
133+
tlv = tlv_hsmd_init_tlvs_new(tmpctx);
134+
tlv->hsm_passphrase = ld->hsm_passphrase;
135+
}
136+
130137
if (!wire_sync_write(ld->hsm_fd, towire_hsmd_init(tmpctx,
131138
&chainparams->bip32_key_version,
132139
chainparams,
133-
ld->config.keypass,
140+
NULL,
134141
ld->dev_force_privkey,
135142
ld->dev_force_bip32_seed,
136143
ld->dev_force_channel_secrets,
137144
ld->dev_force_channel_secrets_shaseed,
138145
HSM_MIN_VERSION,
139-
HSM_MAX_VERSION)))
146+
HSM_MAX_VERSION,
147+
tlv)))
140148
err(EXITCODE_HSM_GENERIC_ERROR, "Writing init msg to hsm");
141149

142150
bip32_base = tal(ld, struct ext_key);
@@ -148,7 +156,7 @@ struct ext_key *hsm_init(struct lightningd *ld)
148156
&unused)) {
149157
/* nothing to do. */
150158
} else {
151-
if (ld->config.keypass)
159+
if (ld->hsm_passphrase)
152160
errx(EXITCODE_HSM_BAD_PASSWORD, "Wrong password for encrypted hsm_secret.");
153161
errx(EXITCODE_HSM_GENERIC_ERROR, "HSM did not give init reply");
154162
}

lightningd/lightningd.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -314,10 +314,10 @@ static struct lightningd *new_lightningd(const tal_t *ctx)
314314
/*~ This is set when a JSON RPC command comes in to shut us down. */
315315
ld->stop_conn = NULL;
316316

317-
/*~ This is used to signal that `hsm_secret` is encrypted, and will
318-
* be set to `true` if the `--encrypted-hsm` option is passed at startup.
317+
/*~ This is used to store the passphrase for hsm_secret if needed.
318+
* It will be set if the `--hsm-passphrase` option is passed at startup.
319319
*/
320-
ld->encrypted_hsm = false;
320+
ld->hsm_passphrase = NULL;
321321

322322
/* This is used to override subdaemons */
323323
strmap_init(&ld->alt_subdaemons);
@@ -1310,11 +1310,6 @@ int main(int argc, char *argv[])
13101310
/*~ This is the ccan/io central poll override from above. */
13111311
io_poll_override(io_poll_lightningd);
13121312

1313-
/*~ If hsm_secret is encrypted, we don't need its encryption key
1314-
* anymore. Note that sodium_munlock() also zeroes the memory.*/
1315-
if (ld->config.keypass)
1316-
discard_key(take(ld->config.keypass));
1317-
13181313
/*~ Our default color and alias are derived from our node id, so we
13191314
* can only set those now (if not set by config options). */
13201315
setup_color_and_alias(ld);

lightningd/lightningd.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@ struct config {
6969
/* Minimal amount of effective funding_satoshis for accepting channels */
7070
u64 min_capacity_sat;
7171

72-
/* This is the key we use to encrypt `hsm_secret`. */
73-
struct secret *keypass;
7472

7573
/* How long before we give up waiting for INIT msg */
7674
u32 connection_timeout_secs;
@@ -378,7 +376,11 @@ struct lightningd {
378376

379377
char *wallet_dsn;
380378

381-
bool encrypted_hsm;
379+
380+
/* HSM passphrase for any format that needs it */
381+
char *hsm_passphrase;
382+
383+
382384
/* What (additional) messages the HSM accepts */
383385
u32 *hsm_capabilities;
384386

lightningd/options.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -604,13 +604,7 @@ static char *opt_set_hsm_password(struct lightningd *ld)
604604
}
605605
prompt(ld, "");
606606

607-
ld->config.keypass = tal(NULL, struct secret);
608-
609-
opt_exitcode = hsm_secret_encryption_key_with_exitcode(passwd, ld->config.keypass, &err_msg);
610-
if (opt_exitcode > 0)
611-
return cast_const(char *, err_msg);
612-
613-
ld->encrypted_hsm = true;
607+
ld->hsm_passphrase = tal_strdup(ld, passwd);
614608
free(passwd);
615609

616610
return NULL;

lightningd/test/run-find_my_abspath.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,6 @@ bool deprecated_ok_(bool deprecated_apis UNNEEDED,
6060
void (*complain)(const char *feat UNNEEDED, bool allowing UNNEEDED, void *) UNNEEDED,
6161
void *cbarg UNNEEDED)
6262
{ fprintf(stderr, "deprecated_ok_ called!\n"); abort(); }
63-
/* Generated stub for discard_key */
64-
void discard_key(struct secret *key TAKES UNNEEDED)
65-
{ fprintf(stderr, "discard_key called!\n"); abort(); }
6663
/* Generated stub for ecdh_hsmd_setup */
6764
void ecdh_hsmd_setup(int hsm_fd UNNEEDED,
6865
void (*failed)(enum status_failreason UNNEEDED,

wallet/test/run-wallet.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -435,9 +435,6 @@ bool invoices_resolve(struct invoices *invoices UNNEEDED,
435435
const struct json_escape *label UNNEEDED,
436436
const struct bitcoin_outpoint *outpoint UNNEEDED)
437437
{ fprintf(stderr, "invoices_resolve called!\n"); abort(); }
438-
/* Generated stub for is_hsm_secret_encrypted */
439-
int is_hsm_secret_encrypted(const char *path UNNEEDED)
440-
{ fprintf(stderr, "is_hsm_secret_encrypted called!\n"); abort(); }
441438
/* Generated stub for json_add_address */
442439
void json_add_address(struct json_stream *response UNNEEDED, const char *fieldname UNNEEDED,
443440
const struct wireaddr *addr UNNEEDED)
@@ -1038,6 +1035,9 @@ void tell_connectd_peer_importance(struct peer *peer UNNEEDED,
10381035
/* Generated stub for tlv_hsmd_dev_preinit_tlvs_new */
10391036
struct tlv_hsmd_dev_preinit_tlvs *tlv_hsmd_dev_preinit_tlvs_new(const tal_t *ctx UNNEEDED)
10401037
{ fprintf(stderr, "tlv_hsmd_dev_preinit_tlvs_new called!\n"); abort(); }
1038+
/* Generated stub for tlv_hsmd_init_tlvs_new */
1039+
struct tlv_hsmd_init_tlvs *tlv_hsmd_init_tlvs_new(const tal_t *ctx UNNEEDED)
1040+
{ fprintf(stderr, "tlv_hsmd_init_tlvs_new called!\n"); abort(); }
10411041
/* Generated stub for to_canonical_invstr */
10421042
const char *to_canonical_invstr(const tal_t *ctx UNNEEDED, const char *invstring UNNEEDED)
10431043
{ fprintf(stderr, "to_canonical_invstr called!\n"); abort(); }
@@ -1141,7 +1141,7 @@ u8 *towire_hsmd_forget_channel(const tal_t *ctx UNNEEDED, const struct node_id *
11411141
u8 *towire_hsmd_get_output_scriptpubkey(const tal_t *ctx UNNEEDED, u64 channel_id UNNEEDED, const struct node_id *peer_id UNNEEDED, const struct pubkey *commitment_point UNNEEDED)
11421142
{ fprintf(stderr, "towire_hsmd_get_output_scriptpubkey called!\n"); abort(); }
11431143
/* Generated stub for towire_hsmd_init */
1144-
u8 *towire_hsmd_init(const tal_t *ctx UNNEEDED, const struct bip32_key_version *bip32_key_version UNNEEDED, const struct chainparams *chainparams UNNEEDED, const struct secret *hsm_encryption_key UNNEEDED, const struct privkey *dev_force_privkey UNNEEDED, const struct secret *dev_force_bip32_seed UNNEEDED, const struct secrets *dev_force_channel_secrets UNNEEDED, const struct sha256 *dev_force_channel_secrets_shaseed UNNEEDED, u32 hsm_wire_min_version UNNEEDED, u32 hsm_wire_max_version UNNEEDED)
1144+
u8 *towire_hsmd_init(const tal_t *ctx UNNEEDED, const struct bip32_key_version *bip32_key_version UNNEEDED, const struct chainparams *chainparams UNNEEDED, const struct secret *hsm_encryption_key UNNEEDED, const struct privkey *dev_force_privkey UNNEEDED, const struct secret *dev_force_bip32_seed UNNEEDED, const struct secrets *dev_force_channel_secrets UNNEEDED, const struct sha256 *dev_force_channel_secrets_shaseed UNNEEDED, u32 hsm_wire_min_version UNNEEDED, u32 hsm_wire_max_version UNNEEDED, const struct tlv_hsmd_init_tlvs *tlvs UNNEEDED)
11451145
{ fprintf(stderr, "towire_hsmd_init called!\n"); abort(); }
11461146
/* Generated stub for towire_hsmd_new_channel */
11471147
u8 *towire_hsmd_new_channel(const tal_t *ctx UNNEEDED, const struct node_id *id UNNEEDED, u64 dbid UNNEEDED)

0 commit comments

Comments
 (0)