Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

repair: add remote signing #2592

Merged
merged 1 commit into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 33 additions & 4 deletions src/app/fdctl/run/tiles/fd_repair.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@
#define CONTACT_IN_IDX 1
#define STAKE_IN_IDX 2
#define STORE_IN_IDX 3
#define SIGN_IN_IDX 4

#define NET_OUT_IDX 0
#define SIGN_OUT_IDX 1

#define MAX_REPAIR_PEERS 40200UL
#define MAX_BUFFER_SIZE ( MAX_REPAIR_PEERS * sizeof(fd_shred_dest_wire_t))
Expand Down Expand Up @@ -100,6 +102,8 @@ struct fd_repair_tile_ctx {

fd_wksp_t * blockstore_wksp;
fd_blockstore_t * blockstore;

fd_keyguard_client_t keyguard_client[1];
};
typedef struct fd_repair_tile_ctx fd_repair_tile_ctx_t;

Expand Down Expand Up @@ -130,6 +134,16 @@ mux_ctx( void * scratch ) {
return (void*)fd_ulong_align_up( (ulong)scratch, alignof(fd_repair_tile_ctx_t) );
}

void
repair_signer( void * signer_ctx,
uchar signature[ static 64 ],
uchar const * buffer,
ulong len,
int sign_type ) {
fd_repair_tile_ctx_t * ctx = (fd_repair_tile_ctx_t *) signer_ctx;
fd_keyguard_client_sign( ctx->keyguard_client, signature, buffer, len, sign_type );
}

static void
send_packet( fd_repair_tile_ctx_t * ctx,
int is_intake,
Expand Down Expand Up @@ -487,17 +501,19 @@ unprivileged_init( fd_topo_t * topo,
fd_topo_tile_t * tile,
void * scratch ) {

if( FD_UNLIKELY( tile->in_cnt != 4 ||
if( FD_UNLIKELY( tile->in_cnt != 5 ||
strcmp( topo->links[ tile->in_link_id[ NET_IN_IDX ] ].name, "net_repair") ||
strcmp( topo->links[ tile->in_link_id[ CONTACT_IN_IDX ] ].name, "gossip_repai" ) ||
strcmp( topo->links[ tile->in_link_id[ STAKE_IN_IDX ] ].name, "stake_out" ) ||
strcmp( topo->links[ tile->in_link_id[ STORE_IN_IDX ] ].name, "store_repair" ) ) ) {
strcmp( topo->links[ tile->in_link_id[ STORE_IN_IDX ] ].name, "store_repair" ) ||
strcmp( topo->links[ tile->in_link_id[ SIGN_IN_IDX ] ].name, "sign_repair" ) ) ) {
FD_LOG_ERR(( "repair tile has none or unexpected input links %lu %s %s",
tile->in_cnt, topo->links[ tile->in_link_id[ 0 ] ].name, topo->links[ tile->in_link_id[ 1 ] ].name ));
}

if( FD_UNLIKELY( tile->out_cnt != 1 ||
strcmp( topo->links[ tile->out_link_id[ NET_OUT_IDX ] ].name, "repair_net" ) ) ) {
if( FD_UNLIKELY( tile->out_cnt != 2 ||
strcmp( topo->links[ tile->out_link_id[ NET_OUT_IDX ] ].name, "repair_net" ) ||
strcmp( topo->links[ tile->out_link_id[ SIGN_OUT_IDX ] ].name, "repair_sign" ) ) ) {
FD_LOG_ERR(( "repair tile has none or unexpected output links %lu %s %s",
tile->out_cnt, topo->links[ tile->out_link_id[ 0 ] ].name, topo->links[ tile->out_link_id[ 1 ] ].name ));
}
Expand Down Expand Up @@ -537,6 +553,17 @@ unprivileged_init( fd_topo_t * topo,
fd_net_create_packet_header_template( ctx->intake_hdr, FD_REPAIR_MAX_PACKET_SIZE, ctx->repair_intake_addr.addr, ctx->src_mac_addr, ctx->repair_intake_listen_port );
fd_net_create_packet_header_template( ctx->serve_hdr, FD_REPAIR_MAX_PACKET_SIZE, ctx->repair_serve_addr.addr, ctx->src_mac_addr, ctx->repair_serve_listen_port );

/* Keyguard setup */
fd_topo_link_t * sign_in = &topo->links[ tile->in_link_id[ SIGN_IN_IDX ] ];
fd_topo_link_t * sign_out = &topo->links[ tile->out_link_id[ SIGN_OUT_IDX ] ];
if( fd_keyguard_client_join( fd_keyguard_client_new( ctx->keyguard_client,
sign_out->mcache,
sign_out->dcache,
sign_in->mcache,
sign_in->dcache ) ) == NULL ) {
FD_LOG_ERR(( "Keyguard join failed" ));
}

/* Blockstore setup */
ulong blockstore_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "blockstore" );
FD_TEST( blockstore_obj_id!=ULONG_MAX );
Expand Down Expand Up @@ -608,6 +635,8 @@ unprivileged_init( fd_topo_t * topo,
ctx->repair_config.serv_send_fun = repair_send_serve_packet;
ctx->repair_config.serv_get_shred_fun = repair_get_shred;
ctx->repair_config.serv_get_parent_fun = repair_get_parent;
ctx->repair_config.sign_fun = repair_signer;
ctx->repair_config.sign_arg = ctx;

if( fd_repair_set_config( ctx->repair, &ctx->repair_config ) ) {
FD_LOG_ERR( ( "error setting repair config" ) );
Expand Down
2 changes: 1 addition & 1 deletion src/app/fdctl/run/tiles/fd_sign.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ unprivileged_init_sensitive( fd_topo_t * topo,
FD_TEST( out_link->mtu==64UL );
} else if ( !strcmp( in_link->name, "repair_sign")) {
ctx->in_role[ i ] = FD_KEYGUARD_ROLE_REPAIR;
FD_TEST( !strcmp( out_link->name, "repair_gossip" ) );
FD_TEST( !strcmp( out_link->name, "sign_repair" ) );
FD_TEST( in_link->mtu==2048UL );
FD_TEST( out_link->mtu==64UL );
} else if ( !strcmp(in_link->name, "voter_sign" ) ) {
Expand Down
10 changes: 10 additions & 0 deletions src/app/fdctl/run/topos/fd_firedancer.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ fd_topo_firedancer( config_t * _config ) {
fd_topob_wksp( topo, "store_repair" );
fd_topob_wksp( topo, "repair_store" );

fd_topob_wksp( topo, "repair_sign" );
fd_topob_wksp( topo, "sign_repair" );

fd_topob_wksp( topo, "store_replay" );
fd_topob_wksp( topo, "replay_poh" );
fd_topob_wksp( topo, "replay_notif" );
Expand Down Expand Up @@ -133,6 +136,8 @@ fd_topo_firedancer( config_t * _config ) {
/**/ fd_topob_link( topo, "store_repair", "store_repair", 0, 128UL, 64UL * 32768UL, 16UL );
/**/ fd_topob_link( topo, "repair_store", "repair_store", 0, 128UL, FD_SHRED_MAX_SZ, 128UL );
/**/ fd_topob_link( topo, "repair_net", "net_repair", 0, config->tiles.net.send_buffer_size, FD_NET_MTU, 1UL );
/**/ fd_topob_link( topo, "repair_sign", "repair_sign", 0, 128UL, 2048UL, 1UL );
/**/ fd_topob_link( topo, "sign_repair", "sign_repair", 0, 128UL, 64UL, 1UL );
/**/ fd_topob_link( topo, "store_replay", "store_replay", 0, 128UL, FD_SHRED_MAX_PER_SLOT * FD_SHRED_MAX_SZ, 16UL );
/**/ fd_topob_link( topo, "replay_poh", "replay_poh", 0, 128UL, 128UL*1024UL*1024UL, 16UL );
/**/ fd_topob_link( topo, "replay_notif", "replay_notif", 0, FD_REPLAY_NOTIF_DEPTH, FD_REPLAY_NOTIF_MTU, 1UL );
Expand Down Expand Up @@ -351,6 +356,11 @@ fd_topo_firedancer( config_t * _config ) {

/**/ fd_topob_tile_in( topo, "pohi", 0UL, "metric_in", "pack_replay", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
fd_topob_tile_out( topo, "pohi", 0UL, "poh_pack", 0UL );
/**/ fd_topob_tile_in( topo, "sign", 0UL, "metric_in", "repair_sign", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
/**/ fd_topob_tile_out( topo, "repair", 0UL, "repair_sign", 0UL );
/**/ fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "sign_repair", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED );
/**/ fd_topob_tile_out( topo, "sign", 0UL, "sign_repair", 0UL );


/* Hacky: Reserve a ulong to allow net0 to pass its PID to its neighbors */
fd_topo_obj_t * net0_pid_obj = fd_topob_obj( topo, "fseq", "net" );
Expand Down
2 changes: 1 addition & 1 deletion src/disco/keyguard/fd_keyguard_authorize.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ fd_keyguard_authorize_repair( fd_keyguard_authority_t const * authority,
int sign_type ) {

if( sign_type != FD_KEYGUARD_SIGN_TYPE_ED25519 ) return 0;
if( sz<144 ) return 0;
if( sz<80 ) return 0;

uint discriminant = fd_uint_load_4( data );
uchar const * sender = data+4;
Expand Down
71 changes: 28 additions & 43 deletions src/flamenco/repair/fd_repair.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#define FD_STAKE_WEIGHTS_MAX (1<<14)
/* Max number of validator clients that we ping */
#define FD_REPAIR_PINGED_MAX (1<<14)
/* Sha256 pre-image size for pings */
#define FD_PING_PRE_IMAGE_SZ (48UL)

/* Test if two hash values are equal */
static int fd_hash_eq( const fd_hash_t * key1, const fd_hash_t * key2 ) {
Expand Down Expand Up @@ -433,17 +435,7 @@ fd_repair_sign_and_send( fd_repair_t * glob,
0 4 */

fd_signature_t sig;
if( glob->sign_fun ) {
(*glob->sign_fun)( glob->sign_arg, sig.uc, buf, buflen, FD_KEYGUARD_SIGN_TYPE_ED25519 );
} else {
fd_sha512_t sha[1];
fd_ed25519_sign( /* sig */ sig.uc,
/* msg */ buf,
/* sz */ buflen,
/* public_key */ glob->public_key->key,
/* private_key */ glob->private_key,
sha );
}
(*glob->sign_fun)( glob->sign_arg, sig.uc, buf, buflen, FD_KEYGUARD_SIGN_TYPE_ED25519 );

/* Reintroduce the signature */

Expand Down Expand Up @@ -599,24 +591,15 @@ fd_repair_recv_ping(fd_repair_t * glob, fd_gossip_ping_t const * ping, fd_gossip
fd_hash_copy( &pong->from, glob->public_key );

/* Generate response hash token */
fd_sha256_t sha[1];
fd_sha256_init( sha );
fd_sha256_append( sha, "SOLANA_PING_PONG", 16UL );
fd_sha256_append( sha, ping->token.uc, 32UL );
fd_sha256_fini( sha, pong->token.uc );
uchar pre_image[FD_PING_PRE_IMAGE_SZ];
memcpy( pre_image, "SOLANA_PING_PONG", 16UL );
memcpy( pre_image+16UL, ping->token.uc, 32UL);

/* Generate response hash token */
fd_sha256_hash( pre_image, FD_PING_PRE_IMAGE_SZ, &pong->token );

/* Sign it */
if( glob->sign_fun ) {
(*glob->sign_fun)( glob->sign_arg, pong->signature.uc, pong->token.uc, 32UL, FD_KEYGUARD_SIGN_TYPE_ED25519 );
} else {
fd_sha512_t sha2[1];
fd_ed25519_sign( /* sig */ pong->signature.uc,
/* msg */ pong->token.uc,
/* sz */ 32UL,
/* public_key */ glob->public_key->key,
/* private_key */ glob->private_key,
sha2 );
}
(*glob->sign_fun)( glob->sign_arg, pong->signature.uc, pre_image, FD_PING_PRE_IMAGE_SZ, FD_KEYGUARD_SIGN_TYPE_SHA256_ED25519 );

fd_bincode_encode_ctx_t ctx;
uchar buf[1024];
Expand Down Expand Up @@ -1035,21 +1018,16 @@ fd_repair_send_ping(fd_repair_t * glob, fd_gossip_peer_addr_t const * addr, fd_p
fd_repair_response_new_disc( &gmsg, fd_repair_response_enum_ping );
fd_gossip_ping_t * ping = &gmsg.inner.ping;
fd_hash_copy( &ping->from, glob->public_key );
for ( ulong i = 0; i < FD_HASH_FOOTPRINT / sizeof(ulong); ++i )
ping->token.ul[i] = val->token.ul[i] = fd_rng_ulong(glob->rng);

if( glob->sign_fun ) {
(*glob->sign_fun)( glob->sign_arg, ping->signature.uc, ping->token.uc, 32UL, FD_KEYGUARD_SIGN_TYPE_SHA256_ED25519 );
} else {
/* FIXME wrong signature for pings */
fd_sha512_t sha[1];
fd_ed25519_sign( /* sig */ ping->signature.uc,
/* msg */ ping->token.uc,
/* sz */ 32UL,
/* public_key */ glob->public_key->key,
/* private_key */ glob->private_key,
sha );
}
for ( ulong i = 0; i < FD_HASH_FOOTPRINT / sizeof(ulong); i++ )
val->token.ul[i] = fd_rng_ulong(glob->rng);

uchar pre_image[FD_PING_PRE_IMAGE_SZ];
memcpy( pre_image, "SOLANA_PING_PONG", 16UL );
memcpy( pre_image+16UL, val->token.uc, 32UL );

fd_sha256_hash( pre_image, FD_PING_PRE_IMAGE_SZ, &ping->token );

(*glob->sign_fun)( glob->sign_arg, ping->signature.uc, pre_image, FD_PING_PRE_IMAGE_SZ, FD_KEYGUARD_SIGN_TYPE_SHA256_ED25519 );

fd_bincode_encode_ctx_t ctx;
uchar buf[1024];
Expand All @@ -1068,10 +1046,17 @@ fd_repair_recv_pong(fd_repair_t * glob, fd_gossip_ping_t const * pong, fd_gossip
return;

/* Verify response hash token */
uchar pre_image[FD_PING_PRE_IMAGE_SZ];
memcpy( pre_image, "SOLANA_PING_PONG", 16UL );
memcpy( pre_image+16UL, val->token.uc, 32UL );

fd_hash_t pre_image_hash;
fd_sha256_hash( pre_image, FD_PING_PRE_IMAGE_SZ, pre_image_hash.uc );

fd_sha256_t sha[1];
fd_sha256_init( sha );
fd_sha256_append( sha, "SOLANA_PING_PONG", 16UL );
fd_sha256_append( sha, val->token.uc, 32UL );
fd_sha256_append( sha, pre_image_hash.uc, 32UL );
fd_hash_t golden;
fd_sha256_fini( sha, golden.uc );

Expand Down
Loading