mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-21 16:14:23 +01:00
hsmd: capability addition: ability to check pubkeys.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
* v3: edd3d288fc88a5470adc2f99abcbfe4d4af29fae0c7a80b4226f28810a815524
|
||||
* v3 without v1: 3f813898f7de490e9126ab817e1c9a29af79c0413d5e37068acedce3ea7b5429
|
||||
* v4: 41a730986c51b930e2d8d12b3169d24966c2004e08d424bdda310edbbde5ba70
|
||||
* v4 with check_pubkey: 48b3992745aa3c6ab6ce5cdaee9082cb7d70017f523d322015e9710bf49fd193
|
||||
*/
|
||||
#define HSM_MIN_VERSION 3
|
||||
#define HSM_MAX_VERSION 4
|
||||
|
||||
@@ -680,6 +680,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c)
|
||||
case WIRE_HSMD_SIGN_LOCAL_HTLC_TX:
|
||||
case WIRE_HSMD_SIGN_REMOTE_HTLC_TO_US:
|
||||
case WIRE_HSMD_SIGN_DELAYED_PAYMENT_TO_US:
|
||||
case WIRE_HSMD_CHECK_PUBKEY:
|
||||
/* Hand off to libhsmd for processing */
|
||||
return req_reply(conn, c,
|
||||
take(hsmd_handle_client_message(
|
||||
@@ -712,6 +713,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c)
|
||||
case WIRE_HSMD_SIGN_BOLT12_REPLY:
|
||||
case WIRE_HSMD_PREAPPROVE_INVOICE_REPLY:
|
||||
case WIRE_HSMD_PREAPPROVE_KEYSEND_REPLY:
|
||||
case WIRE_HSMD_CHECK_PUBKEY_REPLY:
|
||||
return bad_req_fmt(conn, c, c->msg_in,
|
||||
"Received an incoming message of type %s, "
|
||||
"which is not a request",
|
||||
|
||||
@@ -323,3 +323,12 @@ msgdata,hsmd_derive_secret,info,u8,len
|
||||
# Reply with the derived secret
|
||||
msgtype,hsmd_derive_secret_reply,127
|
||||
msgdata,hsmd_derive_secret_reply,secret,secret,
|
||||
|
||||
# Sanity check this pubkey derivation is correct (unhardened only)
|
||||
msgtype,hsmd_check_pubkey,28
|
||||
msgdata,hsmd_check_pubkey,index,u32,
|
||||
msgdata,hsmd_check_pubkey,pubkey,pubkey,
|
||||
|
||||
# Reply
|
||||
msgtype,hsmd_check_pubkey_reply,128
|
||||
msgdata,hsmd_check_pubkey_reply,ok,bool,
|
||||
|
||||
|
@@ -1,5 +1,6 @@
|
||||
#include "config.h"
|
||||
#include <bitcoin/script.h>
|
||||
#include <ccan/array_size/array_size.h>
|
||||
#include <ccan/crypto/hkdf_sha256/hkdf_sha256.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/bolt12_merkle.h>
|
||||
@@ -122,6 +123,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client,
|
||||
case WIRE_HSMD_PREAPPROVE_INVOICE:
|
||||
case WIRE_HSMD_PREAPPROVE_KEYSEND:
|
||||
case WIRE_HSMD_DERIVE_SECRET:
|
||||
case WIRE_HSMD_CHECK_PUBKEY:
|
||||
return (client->capabilities & HSM_CAP_MASTER) != 0;
|
||||
|
||||
/*~ These are messages sent by the HSM so we should never receive them. */
|
||||
@@ -154,6 +156,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client,
|
||||
case WIRE_HSMD_PREAPPROVE_INVOICE_REPLY:
|
||||
case WIRE_HSMD_PREAPPROVE_KEYSEND_REPLY:
|
||||
case WIRE_HSMD_DERIVE_SECRET_REPLY:
|
||||
case WIRE_HSMD_CHECK_PUBKEY_REPLY:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
@@ -533,6 +536,33 @@ static u8 *handle_sign_to_us_tx(struct hsmd_client *c, const u8 *msg_in,
|
||||
return towire_hsmd_sign_tx_reply(NULL, &sig);
|
||||
}
|
||||
|
||||
/* This will check lightningd's key derivation: hopefully any errors in
|
||||
* this process are independent of errors in lightningd! */
|
||||
static u8 *handle_check_pubkey(struct hsmd_client *c, const u8 *msg_in)
|
||||
{
|
||||
u32 index;
|
||||
struct pubkey their_pubkey, our_pubkey;
|
||||
struct privkey our_privkey;
|
||||
|
||||
if (!fromwire_hsmd_check_pubkey(msg_in, &index, &their_pubkey))
|
||||
return hsmd_status_malformed_request(c, msg_in);
|
||||
|
||||
/* We abort if lightningd asks for a stupid index. */
|
||||
bitcoin_key(&our_privkey, &our_pubkey, index);
|
||||
if (!pubkey_eq(&our_pubkey, &their_pubkey)) {
|
||||
hsmd_status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"BIP32 derivation index %u differed:"
|
||||
" they got %s, we got %s",
|
||||
index,
|
||||
type_to_string(tmpctx, struct pubkey,
|
||||
&their_pubkey),
|
||||
type_to_string(tmpctx, struct pubkey,
|
||||
&our_pubkey));
|
||||
}
|
||||
|
||||
return towire_hsmd_check_pubkey_reply(NULL, true);
|
||||
}
|
||||
|
||||
/*~ lightningd asks us to sign a message. I tweeted the spec
|
||||
* in https://twitter.com/rusty_twit/status/1182102005914800128:
|
||||
*
|
||||
@@ -1650,6 +1680,8 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client,
|
||||
return handle_sign_delayed_payment_to_us(client, msg);
|
||||
case WIRE_HSMD_DERIVE_SECRET:
|
||||
return handle_derive_secret(client, msg);
|
||||
case WIRE_HSMD_CHECK_PUBKEY:
|
||||
return handle_check_pubkey(client, msg);
|
||||
|
||||
case WIRE_HSMD_DEV_MEMLEAK:
|
||||
case WIRE_HSMD_ECDH_RESP:
|
||||
@@ -1679,6 +1711,7 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client,
|
||||
case WIRE_HSMD_SIGN_BOLT12_REPLY:
|
||||
case WIRE_HSMD_PREAPPROVE_INVOICE_REPLY:
|
||||
case WIRE_HSMD_PREAPPROVE_KEYSEND_REPLY:
|
||||
case WIRE_HSMD_CHECK_PUBKEY_REPLY:
|
||||
break;
|
||||
}
|
||||
return hsmd_status_bad_request(client, msg, "Unknown request");
|
||||
@@ -1692,6 +1725,7 @@ u8 *hsmd_init(struct secret hsm_secret,
|
||||
u32 salt = 0;
|
||||
struct ext_key master_extkey, child_extkey;
|
||||
struct node_id node_id;
|
||||
static const u32 capabilities[] = { WIRE_HSMD_CHECK_PUBKEY };
|
||||
|
||||
/*~ Don't swap this. */
|
||||
sodium_mlock(secretstuff.hsm_secret.data,
|
||||
@@ -1822,6 +1856,10 @@ u8 *hsmd_init(struct secret hsm_secret,
|
||||
* incompatibility detection) with alternate implementations.
|
||||
*/
|
||||
return take(towire_hsmd_init_reply_v4(
|
||||
NULL, 4, NULL, &node_id, &secretstuff.bip32,
|
||||
NULL, 4,
|
||||
/* Capabilities arg needs to be a tal array */
|
||||
tal_dup_arr(tmpctx, u32, capabilities,
|
||||
ARRAY_SIZE(capabilities), 0),
|
||||
&node_id, &secretstuff.bip32,
|
||||
&bolt12));
|
||||
}
|
||||
|
||||
@@ -3096,3 +3096,9 @@ def test_checkmessage_pubkey_not_found(node_factory):
|
||||
check_result = l1.rpc.checkmessage(msg, zbase, pubkey=pubkey)
|
||||
assert check_result["pubkey"] == pubkey
|
||||
assert check_result["verified"] is True
|
||||
|
||||
|
||||
def test_hsm_capabilities(node_factory):
|
||||
l1 = node_factory.get_node()
|
||||
# This appears before the start message, so it'll already be present.
|
||||
assert l1.daemon.is_in_log(r"hsmd: capability \+WIRE_HSMD_CHECK_PUBKEY")
|
||||
|
||||
Reference in New Issue
Block a user