Line data Source code
1 : #include "fd_keyguard_client.h"
2 : #include "fd_keyguard.h"
3 : #include "../../ballet/bls/fd_bls.h"
4 :
5 : #include "../../tango/mcache/fd_mcache.h"
6 : #include "../../tango/dcache/fd_dcache.h"
7 :
8 : static inline void
9 : fd_keyguard_client_publish( fd_keyguard_client_t * client,
10 : ulong sig,
11 0 : ulong sign_data_len ) {
12 0 : #if FD_HAS_AVX
13 0 : fd_mcache_publish_avx( client->request, client->request_depth, client->request_seq, sig, client->request_chunk, sign_data_len, 0UL, 0UL, 0UL );
14 : #elif FD_HAS_ARM
15 : fd_mcache_publish_arm( client->request, client->request_depth, client->request_seq, sig, client->request_chunk, sign_data_len, 0UL, 0UL, 0UL );
16 : #else
17 : fd_mcache_publish( client->request, client->request_depth, client->request_seq, sig, client->request_chunk, sign_data_len, 0UL, 0UL, 0UL );
18 : #endif
19 0 : }
20 :
21 : void *
22 : fd_keyguard_client_new( void * shmem,
23 : fd_frag_meta_t * request_mcache,
24 : uchar * request_dcache,
25 : fd_frag_meta_t * response_mcache,
26 : uchar * response_dcache,
27 : ulong request_mtu,
28 : ulong response_mtu,
29 : fd_sleep_t * sleep,
30 : ulong request_link_id,
31 0 : ulong sign_tile_id ) {
32 0 : fd_keyguard_client_t * client = (fd_keyguard_client_t*)shmem;
33 :
34 0 : client->sleep = sign_tile_id!=ULONG_MAX ? sleep : NULL;
35 0 : client->request_link_id = request_link_id;
36 0 : client->wake.w = sign_tile_id>>6;
37 0 : client->wake.mask = 1UL<<(sign_tile_id&63UL);
38 :
39 0 : client->request = request_mcache;
40 0 : client->request_depth = fd_mcache_depth( request_mcache );
41 0 : client->request_seq = 0UL;
42 0 : client->request_mem = fd_wksp_containing( request_dcache );
43 0 : client->request_chunk0 = fd_dcache_compact_chunk0( client->request_mem, request_dcache );
44 0 : client->request_wmark = fd_dcache_compact_wmark( client->request_mem, request_dcache, request_mtu );
45 0 : client->request_chunk = client->request_chunk0;
46 0 : client->request_mtu = request_mtu;
47 :
48 0 : client->response = response_mcache;
49 0 : client->response_depth = fd_mcache_depth( response_mcache );
50 0 : client->response_seq = 0UL;
51 0 : client->response_mem = fd_wksp_containing( response_dcache );
52 0 : client->response_chunk0 = fd_dcache_compact_chunk0( client->response_mem, response_dcache );
53 0 : client->response_wmark = fd_dcache_compact_wmark( client->response_mem, response_dcache, response_mtu );
54 0 : client->response_mtu = response_mtu;
55 :
56 0 : return shmem;
57 0 : }
58 :
59 : /* fd_keyguard_client_sign_sz is the common request/response path.
60 : signature_sz is the response size for the request sig, including
61 : public-key queries. */
62 :
63 : static void
64 : fd_keyguard_client_sign_sz( fd_keyguard_client_t * client,
65 : uchar * signature,
66 : ulong signature_sz,
67 : uchar const * sign_data,
68 : ulong sign_data_len,
69 0 : ulong sig ) {
70 0 : FD_TEST( sign_data_len<=client->request_mtu );
71 :
72 0 : uchar * dst = fd_chunk_to_laddr( client->request_mem, client->request_chunk );
73 0 : fd_memcpy( dst, sign_data, sign_data_len );
74 :
75 0 : fd_keyguard_client_publish( client, sig, sign_data_len );
76 0 : client->request_seq = fd_seq_inc( client->request_seq, 1UL );
77 0 : client->request_chunk = fd_dcache_compact_next( client->request_chunk, sign_data_len, client->request_chunk0, client->request_wmark );
78 :
79 0 : if( FD_UNLIKELY( client->sleep ) ) {
80 0 : __atomic_store_n( &client->sleep->seq_mirror[ client->request_link_id ], client->request_seq, __ATOMIC_RELEASE );
81 0 : fd_sleep_wake_check( client->sleep, &client->wake, 1UL );
82 0 : }
83 :
84 0 : fd_frag_meta_t meta;
85 0 : fd_frag_meta_t const * mline;
86 0 : ulong seq_found;
87 0 : long seq_diff;
88 0 : ulong poll_max = ULONG_MAX;
89 0 : FD_MCACHE_WAIT( &meta, mline, seq_found, seq_diff, poll_max, client->response, client->response_depth, client->response_seq );
90 0 : if( FD_UNLIKELY( !poll_max ) ) FD_LOG_ERR(( "sign request timed out while polling" ));
91 0 : if( FD_UNLIKELY( seq_diff ) ) FD_LOG_ERR(( "sign request was overrun while polling" ));
92 0 : FD_HW_MFENCE_LD();
93 :
94 : /* Chunk is in shared memory and might be be written to by an
95 : attacking tile after we validate it, so load once. */
96 0 : ulong chunk = FD_VOLATILE_CONST( mline->chunk );
97 0 : FD_TEST( chunk>=client->response_chunk0 && chunk<=client->response_wmark );
98 :
99 0 : FD_TEST( signature_sz<=client->response_mtu );
100 0 : uchar * src = fd_chunk_to_laddr( client->response_mem, chunk );
101 0 : fd_memcpy( signature, src, signature_sz );
102 :
103 0 : FD_HW_MFENCE_LD();
104 0 : seq_found = fd_frag_meta_seq_query( mline );
105 0 : if( FD_UNLIKELY( fd_seq_ne( seq_found, client->response_seq ) ) ) FD_LOG_ERR(( "sign request was overrun while reading" ));
106 0 : client->response_seq = fd_seq_inc( client->response_seq, 1UL );
107 0 : }
108 :
109 : void
110 : fd_keyguard_client_sign( fd_keyguard_client_t * client,
111 : uchar * signature,
112 : uchar const * sign_data,
113 : ulong sign_data_len,
114 0 : int sign_type ) {
115 0 : ulong signature_sz;
116 0 : switch( sign_type ) {
117 0 : case FD_KEYGUARD_SIGN_TYPE_BLS: signature_sz = FD_BLS_SIG_SZ; break;
118 0 : case FD_KEYGUARD_SIGN_TYPE_BLS_PUBKEY: signature_sz = FD_BLS_PUB_COMPRESSED_SZ; break;
119 0 : default: signature_sz = FD_ED25519_SIG_SZ; break;
120 0 : }
121 0 : fd_keyguard_client_sign_sz( client, signature, signature_sz, sign_data, sign_data_len, (ulong)(uint)sign_type );
122 0 : }
123 :
124 : void
125 : fd_keyguard_client_ag_vote_sign( fd_keyguard_client_t * client,
126 : uchar * signature,
127 : ulong authority_idx,
128 : uchar const * sign_data,
129 0 : ulong sign_data_len ) {
130 0 : FD_CHECK_CRIT( authority_idx==ULONG_MAX || authority_idx<FD_KEYGUARD_AUTH_VOTERS_MAX, "unexpected authorized voter index" );
131 :
132 : /* Same encoding as fd_keyguard_client_vote_txn_sign. */
133 :
134 0 : ulong sig = (ulong)FD_KEYGUARD_SIGN_TYPE_BLS;
135 0 : if( authority_idx!=ULONG_MAX ) sig |= (1UL << 32) | (authority_idx << 33);
136 0 : fd_keyguard_client_sign_sz( client, signature, FD_BLS_SIG_SZ, sign_data, sign_data_len, sig );
137 0 : }
138 :
139 : void
140 : fd_keyguard_client_bls_pubkey( fd_keyguard_client_t * client,
141 : uchar * public_key,
142 0 : ulong authority_idx ) {
143 0 : FD_CHECK_CRIT( authority_idx==ULONG_MAX || authority_idx<FD_KEYGUARD_AUTH_VOTERS_MAX, "unexpected authorized voter index" );
144 0 : fd_keyguard_client_sign( client, public_key, (uchar const *)&authority_idx, sizeof(authority_idx), FD_KEYGUARD_SIGN_TYPE_BLS_PUBKEY );
145 0 : }
146 :
147 : void
148 : fd_keyguard_client_vote_txn_sign( fd_keyguard_client_t * client,
149 : uchar * signatures,
150 : ulong authority_idx,
151 : uchar const * sign_data,
152 0 : ulong sign_data_len ) {
153 0 : FD_CHECK_CRIT( sign_data_len<=client->request_mtu, "the request is too large and will not fit in the mtu" );
154 0 : FD_CHECK_CRIT( authority_idx==ULONG_MAX || authority_idx<FD_KEYGUARD_AUTH_VOTERS_MAX, "unexpected authorized voter index" );
155 :
156 : /* In the signature of the message we use the lower 32 bits to
157 : indicate the sign type. We can use the upper 32 bits to encode if
158 : a second signature is needed and what index the authorized voter
159 : that a signature is needed from.
160 : The least significant bit of the upper 32 is 1 if a second
161 : signature is needed. The next 4 least significant bits of the
162 : upper 32 are used to encode the index of the authorized voter
163 : where the index is [0,16). */
164 :
165 0 : ulong sig = 0UL;
166 0 : if( authority_idx!=ULONG_MAX ) sig |= (1UL << 32) | (authority_idx << 33);
167 0 : ulong signatures_sz = fd_ulong_if( authority_idx!=ULONG_MAX, 2UL*FD_ED25519_SIG_SZ, FD_ED25519_SIG_SZ );
168 0 : fd_keyguard_client_sign_sz( client, signatures, signatures_sz, sign_data, sign_data_len, sig );
169 0 : }
|