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