Line data Source code
1 : #ifndef HEADER_fd_src_waltz_quic_tls_fd_quic_tls_h 2 : #define HEADER_fd_src_waltz_quic_tls_fd_quic_tls_h 3 : 4 : #include "../fd_quic_common.h" 5 : #include "../fd_quic_enum.h" 6 : #include "../../tls/fd_tls.h" 7 : #include "../templ/fd_quic_transport_params.h" 8 : 9 : /* QUIC-TLS 10 : 11 : This defines an API for QUIC-TLS 12 : 13 : General operation: 14 : // seed a CSPRNG 15 : static fd_chacha_rng_t _rng[1]; 16 : fd_chacha_rng_t * rng = fd_chacha_rng_join( 17 : fd_chacha_rng_new( _rng, FD_CHACHA_RNG_MODE_SHIFT ) ); 18 : uchar key[ FD_CHACHA_KEY_SZ ]; 19 : if( FD_UNLIKELY( !fd_rng_secure( key, sizeof(key) ) ) ) abort(); 20 : fd_chacha_rng_init( rng, key, FD_CHACHA_RNG_ALGO_CHACHA8 ); 21 : fd_memzero_explicit( key, sizeof(key) ); 22 : 23 : // set up a quic-tls config object 24 : fd_quic_tls_cfg_t quic_tls_cfg = { 25 : .secret_cb = my_secret_cb, // callback for communicating secrets 26 : 27 : .handshake_complete_cb = my_hs_complete, // called when handshake is complete 28 : 29 : .max_concur_handshakes = 1234, // number of handshakes this object can 30 : // manage concurrently 31 : 32 : .rng = rng, // required, see above 33 : }; 34 : 35 : // create a quic-tls object to manage handshakes: 36 : fd_quic_tls_t * quic_tls = fd_quic_tls_new( quic_tls_cfg ); 37 : 38 : // delete a quic-tls object when it's not needed anymore 39 : fd_quic_delete( quic_tls ); 40 : 41 : // create a client or a server handshake object 42 : // call upon a new connection to manage the connection TLS handshake 43 : fd_quic_tls_hs_t * hs = fd_quic_tls_hs_new( quic_tls, conn_id, conn_id_sz, is_server, transport_params, now ); 44 : 45 : // delete a handshake object 46 : // NULL is allowed here 47 : fd_quic_tls_hs_delete( hs ); 48 : 49 : // call fd_quic_tls_provide_data whenever the peer sends TLS 50 : // handshake data. The peer bootstraps the conversation with a 51 : // zero byte input. 52 : 53 : */ 54 : 55 : /* each TLS handshake requires a number of fd_quic_tls_hs_data structures */ 56 402237 : #define FD_QUIC_TLS_HS_DATA_CNT 16u 57 : 58 : /* alignment of hs_data 59 : must be a power of 2 */ 60 60759 : #define FD_QUIC_TLS_HS_DATA_ALIGN 32u 61 : 62 : /* number of bytes allocated for queued handshake data 63 : must be a multiple of FD_QUIC_TLS_HS_DATA_ALIGN */ 64 121518 : #define FD_QUIC_TLS_HS_DATA_SZ (2048UL) 65 : 66 : /* callback function prototypes */ 67 : 68 : typedef void 69 : (* fd_quic_tls_cb_secret_t)( fd_quic_tls_hs_t * hs, 70 : void * context, 71 : fd_quic_tls_secret_t const * secret ); 72 : 73 : typedef void 74 : (* fd_quic_tls_cb_handshake_complete_t)( fd_quic_tls_hs_t * hs, 75 : void * context ); 76 : 77 : typedef void 78 : (* fd_quic_tls_cb_peer_params_t)( void * context, 79 : uchar const * quic_tp, 80 : ulong quic_tp_sz ); 81 : 82 : struct fd_quic_tls_secret { 83 : uint enc_level; 84 : uchar read_secret [ FD_QUIC_SECRET_SZ ]; 85 : uchar write_secret[ FD_QUIC_SECRET_SZ ]; 86 : }; 87 : 88 : struct fd_quic_tls_cfg { 89 : // callbacks ../crypto/fd_quic_crypto_suites 90 : fd_quic_tls_cb_secret_t secret_cb; 91 : fd_quic_tls_cb_handshake_complete_t handshake_complete_cb; 92 : fd_quic_tls_cb_peer_params_t peer_params_cb; 93 : 94 : ulong max_concur_handshakes; 95 : 96 : /* Signing callback for TLS 1.3 CertificateVerify. Context of the 97 : signer must outlive the tls object. */ 98 : fd_tls_sign_t signer; 99 : 100 : /* Ed25519 public key */ 101 : uchar const * cert_public_key; 102 : 103 : /* rng is a seeded CSPRNG used to generate the TLS random of every 104 : handshake. caller-managed, outlives quic_tls. */ 105 : fd_chacha_rng_t * rng; 106 : 107 : /* alpn: either "solana-tpu" or "alpenglow-v1" */ 108 : uchar const * alpn; 109 : ulong alpn_sz; 110 : }; 111 : 112 : /* structure for organising handshake data */ 113 : struct fd_quic_tls_hs_data { 114 : uchar const * data; 115 : uint data_sz; 116 : uint free_data_sz; /* internal use */ 117 : uint offset; 118 : uint enc_level; 119 : 120 : /* internal use */ 121 : ushort next_idx; /* next in linked list, ~0 for end */ 122 : }; 123 : 124 : struct fd_quic_tls { 125 : /* callbacks */ 126 : fd_quic_tls_cb_secret_t secret_cb; 127 : fd_quic_tls_cb_handshake_complete_t handshake_complete_cb; 128 : fd_quic_tls_cb_peer_params_t peer_params_cb; 129 : 130 : /* ssl related */ 131 : fd_tls_t tls; 132 : }; 133 : 134 728976 : #define FD_QUIC_TLS_HS_DATA_UNUSED ((ushort)~0u) 135 : 136 : struct fd_quic_tls_hs { 137 : /* TLS handshake handles are deliberately placed at the start. 138 : Allows for type punning between fd_quic_tls_hs_t and 139 : fd_tls_estate_{srv,cli}_t. DO NOT MOVE. 140 : Type of handshake object depends on is_server. */ 141 : fd_tls_estate_t hs; 142 : 143 : fd_quic_tls_t * quic_tls; 144 : 145 : int is_server; 146 : int is_hs_complete; 147 : 148 : /* user defined context supplied in callbacks */ 149 : void * context; 150 : 151 : ulong next; /* alloc pool/cache dlist */ 152 : ulong prev; /* cache dlist */ 153 : long birthtime; /* allocation time, used for cache eviction sanity check */ 154 : 155 : /* handshake data 156 : this is data that must be sent to the peer 157 : it consists of an arbitrary list of tuples of: 158 : < "encryption level", array of bytes > 159 : these will be encapsulated and sent in order */ 160 : fd_quic_tls_hs_data_t hs_data[ FD_QUIC_TLS_HS_DATA_CNT ]; 161 : 162 : /* head of hs_data_t free list */ 163 : ushort hs_data_free_idx; 164 : 165 : /* head/tail of hs_data_t pending (to be sent) */ 166 : ushort hs_data_pend_idx[4]; 167 : ushort hs_data_pend_end_idx[4]; 168 : 169 : /* handshake data buffer 170 : allocated in arbitrary chunks 171 : and shared between encryption levels */ 172 : uchar hs_data_buf[ FD_QUIC_TLS_HS_DATA_SZ ]; 173 : uint hs_data_buf_ptr; /* ptr is first unused byte in hs_data_buf */ 174 : uint hs_data_offset[ 4 ]; /* one offset per encoding level */ 175 : 176 : /* Handshake message receive buffer 177 : 178 : rx_hs_buf buffers messages of one encryption level (rx_enc_level). 179 : rx_off is the number of bytes processed by fd_tls. rx_sz is the 180 : number of contiguous bytes received from the peer. */ 181 : 182 : ushort rx_off; 183 : ushort rx_sz; 184 : uchar rx_enc_level; 185 : 186 60696 : # define FD_QUIC_TLS_RX_DATA_SZ (2048UL) 187 : uchar rx_hs_buf[ FD_QUIC_TLS_RX_DATA_SZ ]; 188 : 189 : /* TLS alert code */ 190 : uint alert; 191 : 192 : /* our own QUIC transport params */ 193 : fd_quic_transport_params_t self_transport_params; 194 : 195 : }; 196 : 197 : /* fd_quic_tls_new formats an unused memory region for use as an 198 : fd_quic_tls_t object and joins the caller to it */ 199 : 200 : fd_quic_tls_t * 201 : fd_quic_tls_new( fd_quic_tls_t * mem, 202 : fd_quic_tls_cfg_t * cfg ); 203 : 204 : /* fd_quic_delete unformats a memory region used as an fd_quic_tls_t. 205 : Returns the given pointer on success and NULL if used obviously in error. 206 : Deletes any fd_tls resources. */ 207 : 208 : void * 209 : fd_quic_tls_delete( fd_quic_tls_t * self ); 210 : 211 : fd_quic_tls_hs_t * 212 : fd_quic_tls_hs_new( fd_quic_tls_hs_t * self, 213 : fd_quic_tls_t * quic_tls, 214 : void * context, 215 : int is_server, 216 : fd_quic_transport_params_t const * self_transport_params, 217 : long now ); 218 : 219 : void 220 : fd_quic_tls_hs_delete( fd_quic_tls_hs_t * hs ); 221 : 222 : /* fd_quic_tls_process processes any available TLS handshake messages 223 : from previously received CRYPTO frames. Returns FD_QUIC_SUCCESS if 224 : any number of messages were processed (including no messages in there 225 : is not enough data). Returns FD_QUIC_FAILED if the TLS handshake 226 : failed (not recoverable). */ 227 : 228 : int 229 : fd_quic_tls_process( fd_quic_tls_hs_t * self ); 230 : 231 : 232 : /* fd_quic_tls_get_hs_data 233 : 234 : get oldest queued handshake data from the queue of pending data to sent to peer 235 : 236 : returns 237 : NULL there is no data available 238 : hd_data a pointer to the fd_quic_tls_hs_data_t structure at the head of the queue 239 : 240 : the hd_data and data therein are invalidated by the following 241 : fd_quic_tls_pop_hs_data 242 : fd_quic_tls_hs_delete 243 : 244 : args 245 : self the handshake in question (fine if NULL) 246 : enc_level a pointer for receiving the encryption level 247 : data a pointer for receiving the pointer to the data buffer 248 : data_sz a pointer for receiving the data size */ 249 : fd_quic_tls_hs_data_t * 250 : fd_quic_tls_get_hs_data( fd_quic_tls_hs_t * self, uint enc_level ); 251 : 252 : 253 : /* fd_quic_tls_get_next_hs_data 254 : 255 : get the next unit of handshake data from the queue 256 : 257 : returns NULL if no more available */ 258 : fd_quic_tls_hs_data_t * 259 : fd_quic_tls_get_next_hs_data( fd_quic_tls_hs_t * self, fd_quic_tls_hs_data_t * hs ); 260 : 261 : 262 : /* fd_quic_tls_pop_hs_data 263 : 264 : remove handshake data from head of queue and free associated resources */ 265 : void 266 : fd_quic_tls_pop_hs_data( fd_quic_tls_hs_t * self, uint enc_level ); 267 : 268 : 269 : /* fd_quic_tls_clear_hs_data 270 : 271 : clear all handshake data from a given encryption level. */ 272 : void 273 : fd_quic_tls_clear_hs_data( fd_quic_tls_hs_t * self, uint enc_level ); 274 : 275 : 276 : #endif /* HEADER_fd_src_waltz_quic_tls_fd_quic_tls_h */