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: edd3d288fc88a5470adc2f99abcbfe4d4af29fae0c7a80b4226f28810a815524
|
||||||
* v3 without v1: 3f813898f7de490e9126ab817e1c9a29af79c0413d5e37068acedce3ea7b5429
|
* v3 without v1: 3f813898f7de490e9126ab817e1c9a29af79c0413d5e37068acedce3ea7b5429
|
||||||
* v4: 41a730986c51b930e2d8d12b3169d24966c2004e08d424bdda310edbbde5ba70
|
* v4: 41a730986c51b930e2d8d12b3169d24966c2004e08d424bdda310edbbde5ba70
|
||||||
|
* v4 with check_pubkey: 48b3992745aa3c6ab6ce5cdaee9082cb7d70017f523d322015e9710bf49fd193
|
||||||
*/
|
*/
|
||||||
#define HSM_MIN_VERSION 3
|
#define HSM_MIN_VERSION 3
|
||||||
#define HSM_MAX_VERSION 4
|
#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_LOCAL_HTLC_TX:
|
||||||
case WIRE_HSMD_SIGN_REMOTE_HTLC_TO_US:
|
case WIRE_HSMD_SIGN_REMOTE_HTLC_TO_US:
|
||||||
case WIRE_HSMD_SIGN_DELAYED_PAYMENT_TO_US:
|
case WIRE_HSMD_SIGN_DELAYED_PAYMENT_TO_US:
|
||||||
|
case WIRE_HSMD_CHECK_PUBKEY:
|
||||||
/* Hand off to libhsmd for processing */
|
/* Hand off to libhsmd for processing */
|
||||||
return req_reply(conn, c,
|
return req_reply(conn, c,
|
||||||
take(hsmd_handle_client_message(
|
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_SIGN_BOLT12_REPLY:
|
||||||
case WIRE_HSMD_PREAPPROVE_INVOICE_REPLY:
|
case WIRE_HSMD_PREAPPROVE_INVOICE_REPLY:
|
||||||
case WIRE_HSMD_PREAPPROVE_KEYSEND_REPLY:
|
case WIRE_HSMD_PREAPPROVE_KEYSEND_REPLY:
|
||||||
|
case WIRE_HSMD_CHECK_PUBKEY_REPLY:
|
||||||
return bad_req_fmt(conn, c, c->msg_in,
|
return bad_req_fmt(conn, c, c->msg_in,
|
||||||
"Received an incoming message of type %s, "
|
"Received an incoming message of type %s, "
|
||||||
"which is not a request",
|
"which is not a request",
|
||||||
|
|||||||
@@ -323,3 +323,12 @@ msgdata,hsmd_derive_secret,info,u8,len
|
|||||||
# Reply with the derived secret
|
# Reply with the derived secret
|
||||||
msgtype,hsmd_derive_secret_reply,127
|
msgtype,hsmd_derive_secret_reply,127
|
||||||
msgdata,hsmd_derive_secret_reply,secret,secret,
|
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 "config.h"
|
||||||
#include <bitcoin/script.h>
|
#include <bitcoin/script.h>
|
||||||
|
#include <ccan/array_size/array_size.h>
|
||||||
#include <ccan/crypto/hkdf_sha256/hkdf_sha256.h>
|
#include <ccan/crypto/hkdf_sha256/hkdf_sha256.h>
|
||||||
#include <ccan/tal/str/str.h>
|
#include <ccan/tal/str/str.h>
|
||||||
#include <common/bolt12_merkle.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_INVOICE:
|
||||||
case WIRE_HSMD_PREAPPROVE_KEYSEND:
|
case WIRE_HSMD_PREAPPROVE_KEYSEND:
|
||||||
case WIRE_HSMD_DERIVE_SECRET:
|
case WIRE_HSMD_DERIVE_SECRET:
|
||||||
|
case WIRE_HSMD_CHECK_PUBKEY:
|
||||||
return (client->capabilities & HSM_CAP_MASTER) != 0;
|
return (client->capabilities & HSM_CAP_MASTER) != 0;
|
||||||
|
|
||||||
/*~ These are messages sent by the HSM so we should never receive them. */
|
/*~ 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_INVOICE_REPLY:
|
||||||
case WIRE_HSMD_PREAPPROVE_KEYSEND_REPLY:
|
case WIRE_HSMD_PREAPPROVE_KEYSEND_REPLY:
|
||||||
case WIRE_HSMD_DERIVE_SECRET_REPLY:
|
case WIRE_HSMD_DERIVE_SECRET_REPLY:
|
||||||
|
case WIRE_HSMD_CHECK_PUBKEY_REPLY:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
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);
|
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
|
/*~ lightningd asks us to sign a message. I tweeted the spec
|
||||||
* in https://twitter.com/rusty_twit/status/1182102005914800128:
|
* 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);
|
return handle_sign_delayed_payment_to_us(client, msg);
|
||||||
case WIRE_HSMD_DERIVE_SECRET:
|
case WIRE_HSMD_DERIVE_SECRET:
|
||||||
return handle_derive_secret(client, msg);
|
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_DEV_MEMLEAK:
|
||||||
case WIRE_HSMD_ECDH_RESP:
|
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_SIGN_BOLT12_REPLY:
|
||||||
case WIRE_HSMD_PREAPPROVE_INVOICE_REPLY:
|
case WIRE_HSMD_PREAPPROVE_INVOICE_REPLY:
|
||||||
case WIRE_HSMD_PREAPPROVE_KEYSEND_REPLY:
|
case WIRE_HSMD_PREAPPROVE_KEYSEND_REPLY:
|
||||||
|
case WIRE_HSMD_CHECK_PUBKEY_REPLY:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return hsmd_status_bad_request(client, msg, "Unknown request");
|
return hsmd_status_bad_request(client, msg, "Unknown request");
|
||||||
@@ -1692,6 +1725,7 @@ u8 *hsmd_init(struct secret hsm_secret,
|
|||||||
u32 salt = 0;
|
u32 salt = 0;
|
||||||
struct ext_key master_extkey, child_extkey;
|
struct ext_key master_extkey, child_extkey;
|
||||||
struct node_id node_id;
|
struct node_id node_id;
|
||||||
|
static const u32 capabilities[] = { WIRE_HSMD_CHECK_PUBKEY };
|
||||||
|
|
||||||
/*~ Don't swap this. */
|
/*~ Don't swap this. */
|
||||||
sodium_mlock(secretstuff.hsm_secret.data,
|
sodium_mlock(secretstuff.hsm_secret.data,
|
||||||
@@ -1822,6 +1856,10 @@ u8 *hsmd_init(struct secret hsm_secret,
|
|||||||
* incompatibility detection) with alternate implementations.
|
* incompatibility detection) with alternate implementations.
|
||||||
*/
|
*/
|
||||||
return take(towire_hsmd_init_reply_v4(
|
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));
|
&bolt12));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3096,3 +3096,9 @@ def test_checkmessage_pubkey_not_found(node_factory):
|
|||||||
check_result = l1.rpc.checkmessage(msg, zbase, pubkey=pubkey)
|
check_result = l1.rpc.checkmessage(msg, zbase, pubkey=pubkey)
|
||||||
assert check_result["pubkey"] == pubkey
|
assert check_result["pubkey"] == pubkey
|
||||||
assert check_result["verified"] is True
|
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