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