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