From 4e39b3ff3dfa2e552b0c0bfabee2853e4a38248e Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 17 Oct 2022 11:05:41 +1030 Subject: [PATCH] hsmd: don't use point32 for bolt12, but use pubkeys (though still always 02) This is the one place where we hand point32 over the wire internally, so remove it. This is also our first hsm version change! Signed-off-by: Rusty Russell --- common/bolt12_merkle.c | 6 ++---- common/bolt12_merkle.h | 2 +- common/hsm_version.h | 4 ++-- hsmd/hsmd.c | 5 +++-- hsmd/hsmd_wire.csv | 17 ++++++++++++----- hsmd/libhsmd.c | 21 +++++++++++++++------ lightningd/hsm_control.c | 27 ++++++++++++++++++++------- lightningd/lightningd.h | 2 +- lightningd/offer.c | 2 +- 9 files changed, 57 insertions(+), 29 deletions(-) diff --git a/common/bolt12_merkle.c b/common/bolt12_merkle.c index 76b8e4ab4..1bc5ad359 100644 --- a/common/bolt12_merkle.c +++ b/common/bolt12_merkle.c @@ -224,16 +224,14 @@ void sighash_from_merkle(const char *messagename, * * Since key used to be x-only, we don't hash first byte! */ -void payer_key_tweak(const struct point32 *bolt12, +void payer_key_tweak(const struct pubkey *bolt12, const u8 *publictweak, size_t publictweaklen, struct sha256 *tweak) { u8 rawkey[PUBKEY_CMPR_LEN]; struct sha256_ctx sha; - struct pubkey pk; - pk.pubkey = bolt12->pubkey; - pubkey_to_der(rawkey, &pk); + pubkey_to_der(rawkey, bolt12); sha256_init(&sha); sha256_update(&sha, rawkey + 1, sizeof(rawkey) - 1); diff --git a/common/bolt12_merkle.h b/common/bolt12_merkle.h index 08ae9fc20..cf7f91813 100644 --- a/common/bolt12_merkle.h +++ b/common/bolt12_merkle.h @@ -25,7 +25,7 @@ void sighash_from_merkle(const char *messagename, /** * payer_key_tweak - get the actual tweak to use for a payer_key */ -void payer_key_tweak(const struct point32 *bolt12, +void payer_key_tweak(const struct pubkey *bolt12, const u8 *publictweak, size_t publictweaklen, struct sha256 *tweak); diff --git a/common/hsm_version.h b/common/hsm_version.h index 41f179d69..ea1bdff93 100644 --- a/common/hsm_version.h +++ b/common/hsm_version.h @@ -11,7 +11,7 @@ #define HSM_MIN_VERSION 1 /* wire/hsmd_wire.csv contents version: - * 409cffa355ab6cc76bd298910adca9936a68223267ddc4815ba16aeac5d0acc3 + * 43c435f61de3af0dd7a91514d94b3e0762c962fce5b39be430538f8c6c4b0695 */ -#define HSM_MAX_VERSION 1 +#define HSM_MAX_VERSION 2 #endif /* LIGHTNING_COMMON_HSM_VERSION_H */ diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index 3c4b56192..2bc775704 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -444,7 +444,7 @@ static struct io_plan *init_hsm(struct io_conn *conn, struct secret *hsm_encryption_key; struct bip32_key_version bip32_key_version; u32 minversion, maxversion; - const u32 our_minversion = 1, our_maxversion = 1; + const u32 our_minversion = 2, our_maxversion = 2; /* This must be lightningd. */ assert(is_lightningd(c)); @@ -692,7 +692,8 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_NODE_ANNOUNCEMENT_SIG_REPLY: case WIRE_HSMD_SIGN_WITHDRAWAL_REPLY: case WIRE_HSMD_SIGN_INVOICE_REPLY: - case WIRE_HSMD_INIT_REPLY: + case WIRE_HSMD_INIT_REPLY_V1: + case WIRE_HSMD_INIT_REPLY_V2: case WIRE_HSMD_DERIVE_SECRET_REPLY: case WIRE_HSMSTATUS_CLIENT_BAD_REQUEST: case WIRE_HSMD_SIGN_COMMITMENT_TX_REPLY: diff --git a/hsmd/hsmd_wire.csv b/hsmd/hsmd_wire.csv index 37ff13806..230848ed7 100644 --- a/hsmd/hsmd_wire.csv +++ b/hsmd/hsmd_wire.csv @@ -19,11 +19,18 @@ msgdata,hsmd_init,hsm_wire_min_version,u32, msgdata,hsmd_init,hsm_wire_max_version,u32, #include -msgtype,hsmd_init_reply,111 -msgdata,hsmd_init_reply,node_id,node_id, -msgdata,hsmd_init_reply,bip32,ext_key, -msgdata,hsmd_init_reply,bolt12,point32, -msgdata,hsmd_init_reply,onion_reply_secret,secret, +# DEPRECATED after v0.12, remove in two versions! +msgtype,hsmd_init_reply_v1,111 +msgdata,hsmd_init_reply_v1,node_id,node_id, +msgdata,hsmd_init_reply_v1,bip32,ext_key, +msgdata,hsmd_init_reply_v1,bolt12,u8,32 +msgdata,hsmd_init_reply_v1,onion_reply_secret,secret, + +msgtype,hsmd_init_reply_v2,113 +msgdata,hsmd_init_reply_v2,node_id,node_id, +msgdata,hsmd_init_reply_v2,bip32,ext_key, +msgdata,hsmd_init_reply_v2,bolt12,pubkey, +msgdata,hsmd_init_reply_v2,onion_reply_secret,secret, # Declare a new channel. msgtype,hsmd_new_channel,30 diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index 4fca594ba..b9d3f54b5 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -134,7 +134,8 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_NODE_ANNOUNCEMENT_SIG_REPLY: case WIRE_HSMD_SIGN_WITHDRAWAL_REPLY: case WIRE_HSMD_SIGN_INVOICE_REPLY: - case WIRE_HSMD_INIT_REPLY: + case WIRE_HSMD_INIT_REPLY_V1: + case WIRE_HSMD_INIT_REPLY_V2: case WIRE_HSMSTATUS_CLIENT_BAD_REQUEST: case WIRE_HSMD_SIGN_COMMITMENT_TX_REPLY: case WIRE_HSMD_VALIDATE_COMMITMENT_TX_REPLY: @@ -635,7 +636,7 @@ static u8 *handle_sign_bolt12(struct hsmd_client *c, const u8 *msg_in) node_schnorrkey(&kp, NULL); } else { /* If we're tweaking key, we use bolt12 key */ - struct point32 bolt12; + struct pubkey bolt12; struct sha256 tweak; if (secp256k1_keypair_pub(secp256k1_ctx, @@ -1629,7 +1630,8 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, case WIRE_HSMD_NODE_ANNOUNCEMENT_SIG_REPLY: case WIRE_HSMD_SIGN_WITHDRAWAL_REPLY: case WIRE_HSMD_SIGN_INVOICE_REPLY: - case WIRE_HSMD_INIT_REPLY: + case WIRE_HSMD_INIT_REPLY_V1: + case WIRE_HSMD_INIT_REPLY_V2: case WIRE_HSMSTATUS_CLIENT_BAD_REQUEST: case WIRE_HSMD_SIGN_COMMITMENT_TX_REPLY: case WIRE_HSMD_VALIDATE_COMMITMENT_TX_REPLY: @@ -1652,8 +1654,7 @@ u8 *hsmd_init(struct secret hsm_secret, struct bip32_key_version bip32_key_version) { u8 bip32_seed[BIP32_ENTROPY_LEN_256]; - struct pubkey key; - struct point32 bolt12; + struct pubkey key, bolt12; u32 salt = 0; struct ext_key master_extkey, child_extkey; struct node_id node_id; @@ -1777,6 +1778,14 @@ u8 *hsmd_init(struct secret hsm_secret, hsmd_status_failed(STATUS_FAIL_INTERNAL_ERROR, "Could derive bolt12 public key."); + /* For compatibility, we have to invert y-odd keys */ + u8 raw[PUBKEY_CMPR_LEN]; + pubkey_to_der(raw, &bolt12); + if (raw[0] == SECP256K1_TAG_PUBKEY_ODD) { + raw[0] = SECP256K1_TAG_PUBKEY_EVEN; + pubkey_from_der(raw, sizeof(raw), &bolt12); + } + /*~ We derive a secret for onion_message's self_id so we can tell * if it used a path we created (i.e. do not leak our public id!) */ hkdf_sha256(&onion_reply_secret, sizeof(onion_reply_secret), @@ -1794,7 +1803,7 @@ u8 *hsmd_init(struct secret hsm_secret, /*~ Note: marshalling a bip32 tree only marshals the public side, * not the secrets! So we're not actually handing them out here! */ - return take(towire_hsmd_init_reply( + return take(towire_hsmd_init_reply_v2( NULL, &node_id, &secretstuff.bip32, &bolt12, &onion_reply_secret)); } diff --git a/lightningd/hsm_control.c b/lightningd/hsm_control.c index b1b46db51..1efd6c518 100644 --- a/lightningd/hsm_control.c +++ b/lightningd/hsm_control.c @@ -117,13 +117,26 @@ struct ext_key *hsm_init(struct lightningd *ld) bip32_base = tal(ld, struct ext_key); msg = wire_sync_read(tmpctx, ld->hsm_fd); - if (!fromwire_hsmd_init_reply(msg, - &ld->id, bip32_base, - &ld->bolt12_base, - &ld->onion_reply_secret)) { - if (ld->config.keypass) - errx(EXITCODE_HSM_BAD_PASSWORD, "Wrong password for encrypted hsm_secret."); - errx(EXITCODE_HSM_GENERIC_ERROR, "HSM did not give init reply"); + if (!fromwire_hsmd_init_reply_v2(msg, + &ld->id, bip32_base, + &ld->bolt12_base, + &ld->onion_reply_secret)) { + /* v1 had x-only pubkey */ + u8 pubkey32[33]; + + pubkey32[0] = SECP256K1_TAG_PUBKEY_EVEN; + if (!fromwire_hsmd_init_reply_v1(msg, + &ld->id, bip32_base, + pubkey32 + 1, + &ld->onion_reply_secret)) { + if (ld->config.keypass) + errx(EXITCODE_HSM_BAD_PASSWORD, "Wrong password for encrypted hsm_secret."); + errx(EXITCODE_HSM_GENERIC_ERROR, "HSM did not give init reply"); + } + if (!pubkey_from_der(pubkey32, sizeof(pubkey32), + &ld->bolt12_base)) + errx(EXITCODE_HSM_GENERIC_ERROR, + "HSM gave invalid v1 bolt12_base"); } return bip32_base; diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index 4fe6b45e9..e3b037f7d 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -122,7 +122,7 @@ struct lightningd { struct node_id id; /* The public base for our payer_id keys */ - struct point32 bolt12_base; + struct pubkey bolt12_base; /* The secret we put in onion message paths to know it's ours. */ struct secret onion_reply_secret; diff --git a/lightningd/offer.c b/lightningd/offer.c index b66a4184c..f9fc2081a 100644 --- a/lightningd/offer.c +++ b/lightningd/offer.c @@ -78,7 +78,7 @@ static void hsm_sign_b12(struct lightningd *ld, if (!check_schnorr_sig(&sighash, &key->pubkey, sig)) fatal("HSM gave bad signature %s for pubkey %s", type_to_string(tmpctx, struct bip340sig, sig), - type_to_string(tmpctx, struct point32, key)); + type_to_string(tmpctx, struct pubkey, (struct pubkey *)key)); } static struct command_result *json_createoffer(struct command *cmd,