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