Line data Source code
1 : #define _GNU_SOURCE
2 : #include "../tiles.h"
3 :
4 : #include "generated/fd_sign_tile_seccomp.h"
5 :
6 : #include "../keyguard/fd_keyguard.h"
7 : #include "../keyguard/fd_keyload.h"
8 : #include "../keyguard/fd_keyswitch.h"
9 : #include "../../discof/admin/fd_adminctl.h"
10 : #include "../../ballet/base58/fd_base58.h"
11 : #include "../metrics/fd_metrics.h"
12 : #include "../../ballet/bls/fd_bls.h"
13 :
14 : #include "../../util/hist/fd_histf.h"
15 :
16 : #include <errno.h>
17 : #include <sys/mman.h>
18 :
19 0 : #define MAX_IN (32UL)
20 :
21 : /* fd_sign_in_ctx_t is a context object for each in (producer) mcache
22 : connected to the sign tile. */
23 :
24 : struct fd_sign_out_ctx {
25 : fd_wksp_t * out_mem;
26 : ulong out_chunk0;
27 : ulong out_wmark;
28 : ulong out_chunk;
29 : };
30 : typedef struct fd_sign_out_ctx fd_sign_out_ctx_t;
31 :
32 : struct fd_sign_in_ctx {
33 : int role;
34 : fd_wksp_t * mem;
35 : ulong chunk0;
36 : ulong wmark;
37 : ulong mtu;
38 : };
39 : typedef struct fd_sign_in_ctx fd_sign_in_ctx_t;
40 :
41 : typedef struct {
42 : uchar _data[ FD_KEYGUARD_SIGN_REQ_MTU ];
43 :
44 : /* Pre-staged with the public key base58 encoded, followed by "-" in the first bytes */
45 : ulong public_key_base58_sz;
46 : uchar concat[ FD_BASE58_ENCODED_32_SZ+1UL+9UL ];
47 :
48 : fd_sign_in_ctx_t in[ MAX_IN ];
49 : fd_sign_out_ctx_t out[ MAX_IN ];
50 :
51 : fd_sha512_t sha512 [ 1 ];
52 :
53 : fd_keyswitch_t * keyswitch;
54 :
55 : fd_keyswitch_t * av_keyswitch; /* authorized voters */
56 :
57 : uchar * public_key;
58 : uchar * private_key;
59 :
60 : uchar * bls_private_key; /* alpenglow BLS voting key */
61 :
62 : uchar tip_payment_program [32];
63 : uchar tip_distribution_program[32];
64 :
65 : ulong authorized_voters_cnt;
66 : uchar authorized_voter_pubkeys[ 16UL ][ 32UL ];
67 : uchar authorized_voter_private_keys[ 16UL ][ 32UL ];
68 :
69 : fd_histf_t sign_duration[1];
70 : } fd_sign_ctx_t;
71 :
72 : FD_FN_CONST static inline ulong
73 0 : scratch_align( void ) {
74 0 : return alignof( fd_sign_ctx_t );
75 0 : }
76 :
77 : FD_FN_PURE static inline ulong
78 0 : scratch_footprint( fd_topo_tile_t const * tile ) {
79 0 : (void)tile;
80 0 : ulong l = FD_LAYOUT_INIT;
81 0 : l = FD_LAYOUT_APPEND( l, alignof( fd_sign_ctx_t ), sizeof( fd_sign_ctx_t ) );
82 0 : return FD_LAYOUT_FINI( l, scratch_align() );
83 0 : }
84 :
85 : static void FD_FN_SENSITIVE
86 0 : derive_fields( fd_sign_ctx_t * ctx ) {
87 0 : uchar check_public_key[ 32 ];
88 0 : fd_ed25519_public_from_private( check_public_key, ctx->private_key, ctx->sha512 );
89 0 : if( FD_UNLIKELY( memcmp( check_public_key, ctx->public_key, 32UL ) ) )
90 0 : FD_LOG_EMERG(( "The public key in the identity key file does not match the public key derived from the private key. "
91 0 : "Firedancer will not use the key pair to sign as it might leak the private key." ));
92 :
93 0 : fd_base58_encode_32( ctx->public_key, &ctx->public_key_base58_sz, (char *)ctx->concat );
94 0 : ctx->concat[ ctx->public_key_base58_sz ] = '-';
95 :
96 : /* Alpenglow BLS key derivation, matching
97 : solana_bls_signatures::SecretKey::derive_from_signer: the BLS IKM
98 : is the identity's ed25519 signature over a fixed message. */
99 0 : static char const derive_msg[] = "bls-key-derive-alpenglow";
100 0 : uchar ikm[ 64 ];
101 0 : fd_ed25519_sign( ikm, (uchar const *)derive_msg, sizeof(derive_msg)-1UL, ctx->public_key, ctx->private_key, ctx->sha512 );
102 0 : fd_bls_sec_derive( (fd_bls_sec_t *)fd_type_pun( ctx->bls_private_key ), ikm, sizeof(ikm) );
103 0 : fd_memzero_explicit( ikm, sizeof(ikm) );
104 0 : }
105 :
106 : static void FD_FN_SENSITIVE
107 0 : during_housekeeping_sensitive( fd_sign_ctx_t * ctx ) {
108 0 : if( FD_UNLIKELY( fd_keyswitch_state_query( ctx->keyswitch )==FD_KEYSWITCH_STATE_SWITCH_PENDING ) ) {
109 0 : memcpy( ctx->private_key, ctx->keyswitch->bytes, 32UL );
110 0 : fd_memzero_explicit( ctx->keyswitch->bytes, 32UL );
111 0 : FD_COMPILER_MFENCE();
112 0 : memcpy( ctx->public_key, ctx->keyswitch->bytes+32UL, 32UL );
113 :
114 0 : derive_fields( ctx );
115 0 : fd_keyswitch_state( ctx->keyswitch, FD_KEYSWITCH_STATE_COMPLETED );
116 0 : }
117 :
118 : /* firedancer only */
119 :
120 0 : if( FD_UNLIKELY( ctx->av_keyswitch && fd_keyswitch_state_query( ctx->av_keyswitch )==FD_KEYSWITCH_STATE_SWITCH_PENDING ) ) {
121 0 : ulong param = fd_keyswitch_param_query( ctx->av_keyswitch );
122 0 : if( FD_LIKELY( param==FD_KEYSWITCH_PARAM_AV_ADD ) ) {
123 0 : if( FD_UNLIKELY( ctx->authorized_voters_cnt==16UL ) ) {
124 0 : FD_LOG_WARNING(( "keyswitch failed: maximum number of authorized voters reached" ));
125 0 : fd_memzero_explicit( ctx->av_keyswitch->bytes, 64UL );
126 0 : ctx->av_keyswitch->result = FD_ADD_AUTHORIZED_VOTER_RESULT_MAX_AUTH_VOTERS;
127 0 : fd_keyswitch_state( ctx->av_keyswitch, FD_KEYSWITCH_STATE_FAILED );
128 0 : return;
129 0 : }
130 0 : for( ulong i=0UL; i<ctx->authorized_voters_cnt; i++ ) {
131 0 : if( FD_UNLIKELY( !memcmp( ctx->authorized_voter_pubkeys[ i ], ctx->av_keyswitch->bytes+32UL, 32UL ) ) ) {
132 0 : FD_BASE58_ENCODE_32_BYTES( ctx->authorized_voter_pubkeys[ i ], pubkey_b58 );
133 0 : FD_LOG_WARNING(( "keyswitch failed: authorized voter key duplicate (%s)", pubkey_b58 ));
134 0 : fd_memzero_explicit( ctx->av_keyswitch->bytes, 64UL );
135 0 : ctx->av_keyswitch->result = FD_ADD_AUTHORIZED_VOTER_RESULT_DUPLICATE_AUTH_VOTER;
136 0 : fd_keyswitch_state( ctx->av_keyswitch, FD_KEYSWITCH_STATE_FAILED );
137 0 : return;
138 0 : }
139 0 : }
140 :
141 0 : memcpy( ctx->authorized_voter_private_keys[ ctx->authorized_voters_cnt ], ctx->av_keyswitch->bytes, 32UL );
142 0 : fd_memzero_explicit( ctx->av_keyswitch->bytes, 32UL );
143 0 : FD_COMPILER_MFENCE();
144 0 : memcpy( ctx->authorized_voter_pubkeys[ ctx->authorized_voters_cnt ], ctx->av_keyswitch->bytes + 32UL, 32UL );
145 0 : ctx->authorized_voters_cnt++;
146 0 : } else if( FD_LIKELY( param==FD_KEYSWITCH_PARAM_AV_CLEAR ) ) {
147 0 : fd_memzero_explicit( ctx->authorized_voter_private_keys, sizeof( ctx->authorized_voter_private_keys ) );
148 0 : fd_memzero_explicit( ctx->authorized_voter_pubkeys, sizeof( ctx->authorized_voter_pubkeys ) );
149 0 : ctx->authorized_voters_cnt = 0UL;
150 0 : } else {
151 0 : FD_LOG_CRIT(( "keyswitch: unexpected authorized voter operation %lu", param ));
152 0 : }
153 0 : fd_keyswitch_state( ctx->av_keyswitch, FD_KEYSWITCH_STATE_COMPLETED );
154 0 : }
155 0 : }
156 :
157 : static inline void
158 0 : during_housekeeping( fd_sign_ctx_t * ctx ) {
159 0 : during_housekeeping_sensitive( ctx );
160 0 : }
161 :
162 : static inline void
163 0 : metrics_write( fd_sign_ctx_t * ctx ) {
164 0 : FD_MHIST_COPY( SIGN, SIGN_DURATION_SECONDS, ctx->sign_duration );
165 0 : }
166 :
167 : /* during_frag is called between pairs for sequence number checks, as
168 : we are reading incoming frags. We don't actually need to copy the
169 : fragment here, see fd_dedup.c for why we do this.*/
170 :
171 : static void FD_FN_SENSITIVE
172 : during_frag_sensitive( void * _ctx,
173 : ulong in_idx,
174 : ulong seq,
175 : ulong sig,
176 : ulong chunk,
177 0 : ulong sz ) {
178 0 : (void)seq;
179 0 : (void)sig;
180 :
181 0 : fd_sign_ctx_t * ctx = (fd_sign_ctx_t *)_ctx;
182 0 : FD_TEST( in_idx<MAX_IN );
183 :
184 0 : int role = ctx->in[ in_idx ].role;
185 0 : ulong mtu = ctx->in[ in_idx ].mtu;
186 :
187 0 : if( chunk<ctx->in[ in_idx ].chunk0 || chunk>ctx->in[ in_idx ].wmark || sz>mtu ) {
188 0 : FD_LOG_EMERG(( "oversz or out of bounds signing request (role=%d chunk=%lu sz=%lu mtu=%lu, chunk0=%lu, wmark=%lu)", role, chunk, sz, mtu, ctx->in[ in_idx ].chunk0, ctx->in[ in_idx ].wmark ));
189 0 : }
190 :
191 0 : void * src = fd_chunk_to_laddr( ctx->in[ in_idx ].mem, chunk );
192 0 : fd_memcpy( ctx->_data, src, sz );
193 0 : }
194 :
195 :
196 : static void
197 : during_frag( void * _ctx,
198 : ulong in_idx,
199 : ulong seq,
200 : ulong sig,
201 : ulong chunk,
202 : ulong sz,
203 0 : ulong ctl FD_PARAM_UNUSED ) {
204 0 : during_frag_sensitive( _ctx, in_idx, seq, sig, chunk, sz );
205 0 : }
206 :
207 : static void FD_FN_SENSITIVE
208 : after_frag_sensitive( void * _ctx,
209 : ulong in_idx,
210 : ulong seq,
211 : ulong sig,
212 : ulong sz,
213 : ulong tsorig,
214 : ulong tspub,
215 0 : fd_stem_context_t * stem ) {
216 0 : (void)seq;
217 0 : (void)tspub;
218 :
219 0 : fd_sign_ctx_t * ctx = (fd_sign_ctx_t *)_ctx;
220 :
221 : /* The lower 32 bits are used to specify the sign type.
222 :
223 : If the frag is coming from the repair tile, then the upper 32 bits
224 : contain the repair tile nonce to identify the request.
225 :
226 : If the frag is coming from the send tile, then the upper 32 bits
227 : contain the index of the authorized voter that needs to sign the
228 : vote transaction. The least significant bit of the upper 32 is
229 : used to indicate if a second signature is needed. The next 4 least
230 : significant bits are used to encode the index of the authorized
231 : voter that a signature is needed from. */
232 0 : int sign_type = (int)(uint)(sig);
233 0 : int needs_second_sign = ctx->in[ in_idx ].role==FD_KEYGUARD_ROLE_TXSEND && ((sig>>32) & 1UL);
234 :
235 0 : FD_TEST( in_idx<MAX_IN );
236 :
237 0 : int role = ctx->in[ in_idx ].role;
238 :
239 0 : fd_keyguard_authority_t authority = {0};
240 0 : memcpy( authority.identity_pubkey, ctx->public_key, 32UL );
241 0 : memcpy( authority.tip_payment_program, ctx->tip_payment_program, 32UL );
242 0 : memcpy( authority.tip_distribution_program, ctx->tip_distribution_program, 32UL );
243 :
244 0 : if( FD_UNLIKELY( !fd_keyguard_payload_authorize( &authority, ctx->_data, sz, role, sign_type ) ) ) {
245 0 : FD_LOG_EMERG(( "fd_keyguard_payload_authorize failed (role=%d sign_type=%d)", role, sign_type ));
246 0 : }
247 :
248 0 : long sign_duration = -fd_tickcount();
249 :
250 0 : uchar * dst = fd_chunk_to_laddr( ctx->out[ in_idx ].out_mem, ctx->out[ in_idx ].out_chunk );
251 0 : ulong out_sz = 64UL;
252 :
253 0 : switch( sign_type ) {
254 0 : case FD_KEYGUARD_SIGN_TYPE_ED25519: {
255 0 : fd_ed25519_sign( dst, ctx->_data, sz, ctx->public_key, ctx->private_key, ctx->sha512 );
256 0 : if( needs_second_sign ) {
257 0 : ulong authority_idx = (sig >> 33) & 0xFUL;
258 0 : if( FD_UNLIKELY( authority_idx>=ctx->authorized_voters_cnt ) )
259 0 : FD_LOG_CRIT(( "invalid sign request from in_idx=%lu: authority_idx=%lu out of range (authorized_voters_cnt=%lu)", in_idx, authority_idx, ctx->authorized_voters_cnt ));
260 0 : fd_ed25519_sign( dst+64UL, ctx->_data, sz, ctx->authorized_voter_pubkeys[ authority_idx ], ctx->authorized_voter_private_keys[ authority_idx ], ctx->sha512 );
261 0 : out_sz = 128UL;
262 0 : }
263 0 : break;
264 0 : }
265 0 : case FD_KEYGUARD_SIGN_TYPE_SHA256_ED25519: {
266 0 : uchar hash[ 32 ];
267 0 : fd_sha256_hash( ctx->_data, sz, hash );
268 0 : fd_ed25519_sign( dst, hash, 32UL, ctx->public_key, ctx->private_key, ctx->sha512 );
269 0 : break;
270 0 : }
271 0 : case FD_KEYGUARD_SIGN_TYPE_PUBKEY_CONCAT_ED25519: {
272 0 : memcpy( ctx->concat+ctx->public_key_base58_sz+1UL, ctx->_data, 9UL );
273 0 : fd_ed25519_sign( dst, ctx->concat, ctx->public_key_base58_sz+1UL+9UL, ctx->public_key, ctx->private_key, ctx->sha512 );
274 0 : break;
275 0 : }
276 0 : case FD_KEYGUARD_SIGN_TYPE_BLS: {
277 0 : fd_bls_sig_t bls_sig[1];
278 0 : fd_bls_sec_sign( (fd_bls_sec_t const *)fd_type_pun_const( ctx->bls_private_key ), ctx->_data, sz, bls_sig );
279 0 : fd_bls_sig_ser( bls_sig, dst );
280 0 : out_sz = FD_KEYGUARD_BLS_SIG_SZ;
281 0 : break;
282 0 : }
283 0 : default:
284 0 : FD_LOG_EMERG(( "invalid sign type: %d", sign_type ));
285 0 : }
286 :
287 0 : sign_duration += fd_tickcount();
288 0 : fd_histf_sample( ctx->sign_duration, (ulong)sign_duration );
289 :
290 0 : fd_stem_publish( stem, in_idx, sig, ctx->out[ in_idx ].out_chunk, out_sz, 0UL, tsorig, 0UL );
291 0 : ctx->out[ in_idx ].out_chunk = fd_dcache_compact_next( ctx->out[ in_idx ].out_chunk, out_sz, ctx->out[ in_idx ].out_chunk0, ctx->out[ in_idx ].out_wmark );
292 0 : }
293 :
294 : static void
295 : after_frag( void * _ctx,
296 : ulong in_idx,
297 : ulong seq,
298 : ulong sig,
299 : ulong sz,
300 : ulong tsorig,
301 : ulong tspub,
302 0 : fd_stem_context_t * stem ) {
303 0 : after_frag_sensitive( _ctx, in_idx, seq, sig, sz, tsorig, tspub, stem );
304 0 : }
305 :
306 : static void FD_FN_SENSITIVE
307 : privileged_init_sensitive( fd_topo_t const * topo,
308 0 : fd_topo_tile_t const * tile ) {
309 0 : void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
310 0 : FD_SCRATCH_ALLOC_INIT( l, scratch );
311 0 : fd_sign_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof( fd_sign_ctx_t ), sizeof( fd_sign_ctx_t ) );
312 :
313 0 : uchar * identity_key = fd_keyload_mprotect_wr( fd_keyload_load( tile->sign.identity_key_path, /* pubkey only: */ 0 ), /* public_key_only: */ 0 );
314 0 : ctx->private_key = identity_key;
315 0 : ctx->public_key = identity_key + 32UL;
316 :
317 0 : ctx->bls_private_key = fd_keyload_alloc_protected_pages( 1UL, 2UL );
318 :
319 0 : ctx->authorized_voters_cnt = tile->sign.authorized_voter_paths_cnt;
320 0 : for( ulong i=0UL; i<tile->sign.authorized_voter_paths_cnt; i++ ) {
321 0 : uchar const * authorized_voter_key = fd_keyload_load( tile->sign.authorized_voter_paths[ i ], /* pubkey only: */ 0 );
322 0 : memcpy( ctx->authorized_voter_private_keys[ i ], authorized_voter_key, 32UL );
323 0 : memcpy( ctx->authorized_voter_pubkeys[ i ], authorized_voter_key + 32UL, 32UL );
324 0 : }
325 :
326 : /* The stack can be taken over and reorganized by under AddressSanitizer,
327 : which causes this code to fail. */
328 : #if FD_HAS_ASAN
329 : FD_LOG_WARNING(( "!!! SECURITY WARNING !!! YOU ARE RUNNING THE SIGNING TILE "
330 : "WITH ADDRESS SANITIZER ENABLED. THIS CAN LEAK SENSITIVE "
331 : "DATA INCLUDING YOUR PRIVATE KEYS INTO CORE DUMPS IF THIS "
332 : "PROCESS ABORTS. IT IS HIGHLY ADVISED TO NOT TO RUN IN THIS "
333 : "MODE IN PRODUCTION!" ));
334 : #else
335 : /* Prevent the stack from showing up in core dumps just in case the
336 : private key somehow ends up in there. */
337 0 : FD_TEST( fd_tile_stack0() );
338 0 : FD_TEST( fd_tile_stack_sz() );
339 0 : if( FD_UNLIKELY( madvise( (void*)fd_tile_stack0(), fd_tile_stack_sz(), MADV_DONTDUMP ) ) )
340 0 : FD_LOG_ERR(( "madvise failed (%i-%s)", errno, fd_io_strerror( errno ) ));
341 0 : #endif
342 0 : }
343 :
344 : static void
345 : privileged_init( fd_topo_t const * topo,
346 0 : fd_topo_tile_t const * tile ) {
347 0 : privileged_init_sensitive( topo, tile );
348 0 : }
349 :
350 : static void FD_FN_SENSITIVE
351 : unprivileged_init_sensitive( fd_topo_t const * topo,
352 0 : fd_topo_tile_t const * tile ) {
353 0 : void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
354 :
355 0 : FD_SCRATCH_ALLOC_INIT( l, scratch );
356 0 : fd_sign_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof( fd_sign_ctx_t ), sizeof( fd_sign_ctx_t ) );
357 0 : FD_TEST( fd_sha512_join( fd_sha512_new( ctx->sha512 ) ) );
358 :
359 0 : FD_TEST( tile->in_cnt<=MAX_IN );
360 0 : FD_TEST( tile->in_cnt==tile->out_cnt );
361 :
362 0 : fd_histf_join( fd_histf_new( ctx->sign_duration, FD_MHIST_SECONDS_MIN( SIGN, SIGN_DURATION_SECONDS ),
363 0 : FD_MHIST_SECONDS_MAX( SIGN, SIGN_DURATION_SECONDS ) ) );
364 :
365 0 : ctx->keyswitch = fd_keyswitch_join( fd_topo_obj_laddr( topo, tile->id_keyswitch_obj_id ) );
366 0 : derive_fields( ctx );
367 :
368 0 : if( FD_LIKELY( tile->av_keyswitch_obj_id!=ULONG_MAX ) ) {
369 0 : ctx->av_keyswitch = fd_keyswitch_join( fd_topo_obj_laddr( topo, tile->av_keyswitch_obj_id ) );
370 0 : FD_TEST( ctx->av_keyswitch );
371 0 : } else {
372 0 : ctx->av_keyswitch = NULL;
373 0 : }
374 :
375 0 : memcpy( ctx->tip_payment_program, tile->sign.bundle.tip_payment_program_addr, 32UL );
376 0 : memcpy( ctx->tip_distribution_program, tile->sign.bundle.tip_distribution_program_addr, 32UL );
377 :
378 0 : for( ulong i=0UL; i<MAX_IN; i++ ) ctx->in[ i ].role = -1;
379 :
380 0 : for( ulong i=0UL; i<tile->in_cnt; i++ ) {
381 0 : fd_topo_link_t const * in_link = &topo->links[ tile->in_link_id[ i ] ];
382 0 : fd_topo_link_t const * out_link = &topo->links[ tile->out_link_id[ i ] ];
383 :
384 0 : if( in_link->mtu > FD_KEYGUARD_SIGN_REQ_MTU ) FD_LOG_CRIT(( "oversz link[%lu].mtu=%lu", i, in_link->mtu ));
385 0 : ctx->in[ i ].mem = fd_wksp_containing( in_link->dcache );
386 0 : ctx->in[ i ].mtu = in_link->mtu;
387 0 : ctx->in[ i ].chunk0 = fd_dcache_compact_chunk0( ctx->in[ i ].mem, in_link->dcache );
388 0 : ctx->in[ i ].wmark = fd_dcache_compact_wmark( ctx->in[ i ].mem, in_link->dcache, in_link->mtu );
389 :
390 0 : ctx->out[ i ].out_mem = fd_wksp_containing( out_link->dcache );
391 0 : ctx->out[ i ].out_chunk0 = fd_dcache_compact_chunk0( ctx->out[ i ].out_mem, out_link->dcache );
392 0 : ctx->out[ i ].out_wmark = fd_dcache_compact_wmark( ctx->out[ i ].out_mem, out_link->dcache, out_link->mtu );
393 0 : ctx->out[ i ].out_chunk = ctx->out[ i ].out_chunk0;
394 :
395 0 : if( !strcmp( in_link->name, "shred_sign" ) ) {
396 0 : ctx->in[ i ].role = FD_KEYGUARD_ROLE_LEADER;
397 0 : FD_TEST( !strcmp( out_link->name, "sign_shred" ) );
398 0 : FD_TEST( in_link->mtu==32UL );
399 0 : FD_TEST( out_link->mtu==64UL );
400 0 : } else if ( !strcmp( in_link->name, "gossip_sign" ) ) {
401 0 : ctx->in[ i ].role = FD_KEYGUARD_ROLE_GOSSIP;
402 0 : FD_TEST( !strcmp( out_link->name, "sign_gossip" ) );
403 0 : FD_TEST( in_link->mtu==2048UL );
404 0 : FD_TEST( out_link->mtu==64UL );
405 0 : } else if ( !strcmp( in_link->name, "repair_sign" ) ) {
406 0 : ctx->in[ i ].role = FD_KEYGUARD_ROLE_REPAIR;
407 0 : FD_TEST( !strcmp( out_link->name, "sign_repair" ) );
408 0 : FD_TEST( in_link->mtu==124UL ); // FD_REPAIR_MAX_PREIMAGE_SZ
409 0 : FD_TEST( out_link->mtu==64UL );
410 0 : } else if ( !strcmp(in_link->name, "txsend_sign" ) ) {
411 0 : ctx->in[ i ].role = FD_KEYGUARD_ROLE_TXSEND;
412 0 : FD_TEST( !strcmp( out_link->name, "sign_txsend" ) );
413 0 : FD_TEST( in_link->mtu==FD_TXN_MTU_V0 );
414 0 : FD_TEST( out_link->mtu==64UL*2UL );
415 0 : } else if( !strcmp(in_link->name, "bundle_sign" ) ) {
416 0 : ctx->in[ i ].role = FD_KEYGUARD_ROLE_BUNDLE;
417 0 : FD_TEST( !strcmp( out_link->name, "sign_bundle" ) );
418 0 : FD_TEST( in_link->mtu==9UL );
419 0 : FD_TEST( out_link->mtu==64UL );
420 0 : } else if( !strcmp(in_link->name, "event_sign" ) ) {
421 0 : ctx->in[ i ].role = FD_KEYGUARD_ROLE_EVENT;
422 0 : FD_TEST( !strcmp( out_link->name, "sign_event" ) );
423 0 : FD_TEST( in_link->mtu==317UL );
424 0 : FD_TEST( out_link->mtu==64UL );
425 0 : } else if( !strcmp(in_link->name, "pack_sign" ) ) {
426 0 : ctx->in[ i ].role = FD_KEYGUARD_ROLE_BUNDLE_CRANK;
427 0 : FD_TEST( !strcmp( out_link->name, "sign_pack" ) );
428 0 : FD_TEST( in_link->mtu==1232UL );
429 0 : FD_TEST( out_link->mtu==64UL );
430 0 : } else if( !strcmp(in_link->name, "rserve_sign" ) ) {
431 0 : ctx->in[ i ].role = FD_KEYGUARD_ROLE_RSERVE;
432 0 : FD_TEST( !strcmp( out_link->name, "sign_rserve" ) );
433 0 : FD_TEST( in_link->mtu==32UL );
434 0 : FD_TEST( out_link->mtu==64UL );
435 0 : } else if( !strcmp(in_link->name, "votor_sign" ) ) {
436 0 : ctx->in[ i ].role = FD_KEYGUARD_ROLE_VOTOR;
437 0 : FD_TEST( !strcmp( out_link->name, "sign_votor" ) );
438 0 : FD_TEST( in_link->mtu==130UL );
439 0 : FD_TEST( out_link->mtu==FD_KEYGUARD_BLS_SIG_SZ );
440 0 : } else {
441 0 : FD_LOG_CRIT(( "unexpected link %s", in_link->name ));
442 0 : }
443 0 : }
444 :
445 0 : ulong scratch_top = FD_SCRATCH_ALLOC_FINI( l, scratch_align() );
446 0 : if( FD_UNLIKELY( scratch_top > (ulong)scratch + scratch_footprint( tile ) ) )
447 0 : FD_LOG_ERR(( "scratch overflow %lu %lu %lu", scratch_top - (ulong)scratch - scratch_footprint( tile ), scratch_top, (ulong)scratch + scratch_footprint( tile ) ));
448 0 : }
449 :
450 : static void
451 : unprivileged_init( fd_topo_t const * topo,
452 0 : fd_topo_tile_t const * tile ) {
453 0 : unprivileged_init_sensitive( topo, tile );
454 0 : }
455 :
456 : static ulong
457 : populate_allowed_seccomp( fd_topo_t const * topo,
458 : fd_topo_tile_t const * tile,
459 : ulong out_cnt,
460 0 : struct sock_filter * out ) {
461 0 : (void)topo;
462 0 : (void)tile;
463 :
464 0 : populate_sock_filter_policy_fd_sign_tile( out_cnt, out, (uint)fd_log_private_logfile_fd() );
465 0 : return sock_filter_policy_fd_sign_tile_instr_cnt;
466 0 : }
467 :
468 : static ulong
469 : populate_allowed_fds( fd_topo_t const * topo,
470 : fd_topo_tile_t const * tile,
471 : ulong out_fds_cnt,
472 0 : int * out_fds ) {
473 0 : (void)topo;
474 0 : (void)tile;
475 :
476 0 : if( FD_UNLIKELY( out_fds_cnt<2UL ) ) FD_LOG_ERR(( "out_fds_cnt %lu", out_fds_cnt ));
477 :
478 0 : ulong out_cnt = 0;
479 0 : out_fds[ out_cnt++ ] = 2; /* stderr */
480 0 : if( FD_LIKELY( -1!=fd_log_private_logfile_fd() ) )
481 0 : out_fds[ out_cnt++ ] = fd_log_private_logfile_fd(); /* logfile */
482 0 : return out_cnt;
483 0 : }
484 :
485 0 : #define STEM_BURST (1UL)
486 :
487 : /* See explanation in fd_pack */
488 0 : #define STEM_LAZY (128L*3000L)
489 :
490 0 : #define STEM_CALLBACK_CONTEXT_TYPE fd_sign_ctx_t
491 0 : #define STEM_CALLBACK_CONTEXT_ALIGN alignof(fd_sign_ctx_t)
492 :
493 0 : #define STEM_CALLBACK_DURING_HOUSEKEEPING during_housekeeping
494 0 : #define STEM_CALLBACK_METRICS_WRITE metrics_write
495 0 : #define STEM_CALLBACK_DURING_FRAG during_frag
496 0 : #define STEM_CALLBACK_AFTER_FRAG after_frag
497 :
498 : #include "../../disco/stem/fd_stem.c"
499 :
500 : fd_topo_run_tile_t fd_tile_sign = {
501 : .name = "sign",
502 : .populate_allowed_seccomp = populate_allowed_seccomp,
503 : .populate_allowed_fds = populate_allowed_fds,
504 : .scratch_align = scratch_align,
505 : .scratch_footprint = scratch_footprint,
506 : .privileged_init = privileged_init,
507 : .unprivileged_init = unprivileged_init,
508 : .run = stem_run,
509 : };
|