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