Line data Source code
1 : #include "fd_quic_tls.h"
2 : #include "../fd_quic_private.h"
3 : #include "../../../ballet/ed25519/fd_ed25519.h"
4 : #include "../../../ballet/ed25519/fd_x25519.h"
5 : #include "../../../ballet/x509/fd_x509_mock.h"
6 : #include "../../../util/fd_util.h"
7 :
8 : #include <errno.h>
9 : #include <stdlib.h>
10 : #include <string.h>
11 : #include <sys/uio.h>
12 :
13 : /* fd_tls callbacks provided by fd_quic *******************************/
14 :
15 : /* fd_quic_tls_sendmsg is called by fd_tls when fd_quic should send a
16 : CRYPTO frame to the peer. Currently, we can assume that the
17 : encryption_level will never decrease (INITIAL => HANDSHAKE => APP) */
18 :
19 : int
20 : fd_quic_tls_sendmsg( void const * handshake,
21 : void const * record,
22 : ulong record_sz,
23 : uint encryption_level,
24 : int flush );
25 :
26 : /* fd_quic_tls_secrets is called by fd_tls when new encryption keys
27 : become available. Currently, this is called at most two times per
28 : connection: For the handshake secrets, and for the initial app-level
29 : secrets. */
30 :
31 : void
32 : fd_quic_tls_secrets( void const * handshake,
33 : void const * recv_secret,
34 : void const * send_secret,
35 : uint encryption_level );
36 :
37 : /* fd_quic_tls_rand is the RNG provided to fd_tls. Note: This is
38 : a layering violation ... The user should pass the CSPRNG handle to
39 : both fd_quic and fd_tls. Currently, implemented via the getrandom()
40 : syscall ... Inefficient! */
41 :
42 : void *
43 : fd_quic_tls_rand( void * ctx,
44 : void * buf,
45 : ulong bufsz );
46 :
47 : /* fd_quic_tls_tp_self is called by fd_tls to retrieve fd_quic's QUIC
48 : transport parameters. */
49 :
50 : ulong
51 : fd_quic_tls_tp_self( void * handshake,
52 : uchar * quic_tp,
53 : ulong quic_tp_bufsz );
54 :
55 : /* fd_quic_tls_tp_self is called by fd_tls to inform fd_quic of the
56 : peer's QUIC transport parameters. */
57 :
58 : void
59 : fd_quic_tls_tp_peer( void * handshake,
60 : uchar const * quic_tp,
61 : ulong quic_tp_sz );
62 :
63 : /* fd_quic_tls lifecycle API ******************************************/
64 :
65 : ulong
66 10920 : fd_quic_tls_align( void ) {
67 10920 : return alignof( fd_quic_tls_t );
68 10920 : }
69 :
70 : /* fd_quic_tls_layout_t describes the memory layout on an fd_quic_tls_t */
71 : struct fd_quic_tls_layout {
72 : ulong handshakes_off;
73 : ulong handshakes_used_off;
74 : };
75 : typedef struct fd_quic_tls_layout fd_quic_tls_layout_t;
76 :
77 : ulong
78 : fd_quic_tls_footprint_ext( ulong handshake_cnt,
79 14244 : fd_quic_tls_layout_t * layout ) {
80 :
81 14244 : ulong off = sizeof( fd_quic_tls_t );
82 :
83 14244 : off = fd_ulong_align_up( off, alignof( fd_quic_tls_hs_t ) );
84 14244 : layout->handshakes_off = off;
85 14244 : off += handshake_cnt * sizeof( fd_quic_tls_hs_t );
86 :
87 : /* no align required */
88 14244 : layout->handshakes_used_off = off;
89 14244 : off += handshake_cnt; /* used handshakes */
90 :
91 14244 : return off;
92 14244 : }
93 :
94 : ulong
95 10920 : fd_quic_tls_footprint( ulong handshake_cnt ) {
96 10920 : fd_quic_tls_layout_t layout;
97 10920 : return fd_quic_tls_footprint_ext( handshake_cnt, &layout );
98 10920 : }
99 :
100 : static void
101 : fd_quic_tls_init( fd_tls_t * tls,
102 : fd_tls_sign_t signer,
103 : uchar const cert_public_key[ static 32 ] );
104 :
105 : fd_quic_tls_t *
106 : fd_quic_tls_new( void * mem,
107 3324 : fd_quic_tls_cfg_t * cfg ) {
108 :
109 3324 : if( FD_UNLIKELY( !mem ) ) {
110 0 : FD_LOG_WARNING(( "NULL mem" ));
111 0 : return NULL;
112 0 : }
113 3324 : if( FD_UNLIKELY( !cfg ) ) {
114 0 : FD_LOG_WARNING(( "NULL cfg" ));
115 0 : return NULL;
116 0 : }
117 :
118 3324 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, alignof( fd_quic_tls_t ) ) ) ) {
119 0 : FD_LOG_WARNING(( "misaligned mem" ));
120 0 : return NULL;
121 0 : }
122 :
123 3324 : ulong handshake_cnt = cfg->max_concur_handshakes;
124 :
125 3324 : fd_quic_tls_layout_t layout = {0};
126 3324 : ulong footprint = fd_quic_tls_footprint_ext( handshake_cnt, &layout );
127 3324 : if( FD_UNLIKELY( !footprint ) ) {
128 0 : FD_LOG_WARNING(( "invalid footprint for config" ));
129 0 : return NULL;
130 0 : }
131 :
132 3324 : fd_quic_tls_t * self = (fd_quic_tls_t *)mem;
133 :
134 3324 : if( FD_UNLIKELY( (!cfg->secret_cb ) |
135 3324 : (!cfg->handshake_complete_cb) |
136 3324 : (!cfg->peer_params_cb ) ) ) {
137 0 : FD_LOG_WARNING(( "Missing callbacks" ));
138 0 : return NULL;
139 0 : }
140 :
141 3324 : self->secret_cb = cfg->secret_cb;
142 3324 : self->handshake_complete_cb = cfg->handshake_complete_cb;
143 3324 : self->peer_params_cb = cfg->peer_params_cb;
144 3324 : self->max_concur_handshakes = cfg->max_concur_handshakes;
145 :
146 3324 : ulong handshakes_laddr = (ulong)mem + layout.handshakes_off;
147 3324 : fd_quic_tls_hs_t * handshakes = (fd_quic_tls_hs_t *)(handshakes_laddr);
148 3324 : self->handshakes = handshakes;
149 :
150 : /* FIXME use a bitmap instead of an array */
151 3324 : ulong used_handshakes_laddr = (ulong)mem + layout.handshakes_used_off;
152 3324 : uchar * used_handshakes = (uchar *)(used_handshakes_laddr);
153 3324 : self->used_handshakes = used_handshakes;
154 :
155 : // set all to free
156 3324 : fd_memset( used_handshakes, 0, (ulong)self->max_concur_handshakes );
157 :
158 : /* Initialize fd_tls */
159 3324 : fd_quic_tls_init( &self->tls, cfg->signer, cfg->cert_public_key );
160 :
161 3324 : return self;
162 3324 : }
163 :
164 : /* fd_quic_tls_init is called as part of fd_quic_tls_new. It sets up
165 : the embedded fd_tls instance. */
166 :
167 : static void
168 : fd_quic_tls_init( fd_tls_t * tls,
169 : fd_tls_sign_t signer,
170 3324 : uchar const cert_public_key[ static 32 ] ) {
171 3324 : tls = fd_tls_new( tls );
172 3324 : *tls = (fd_tls_t) {
173 3324 : .quic = 1,
174 3324 : .rand = {
175 3324 : .ctx = NULL,
176 3324 : .rand_fn = fd_quic_tls_rand
177 3324 : },
178 3324 : .sign = signer,
179 3324 : .secrets_fn = fd_quic_tls_secrets,
180 3324 : .sendmsg_fn = fd_quic_tls_sendmsg,
181 :
182 3324 : .quic_tp_self_fn = fd_quic_tls_tp_self,
183 3324 : .quic_tp_peer_fn = fd_quic_tls_tp_peer,
184 3324 : };
185 :
186 : /* Generate X25519 key */
187 3324 : if( FD_UNLIKELY( !fd_rng_secure( tls->kex_private_key, 32UL ) ) )
188 0 : FD_LOG_ERR(( "fd_rng_secure failed: %s", fd_io_strerror( errno ) ));
189 3324 : fd_x25519_public( tls->kex_public_key, tls->kex_private_key );
190 :
191 : /* Set up Ed25519 key */
192 3324 : fd_memcpy( tls->cert_public_key, cert_public_key, 32UL );
193 :
194 : /* Generate X.509 cert */
195 3324 : fd_x509_mock_cert( tls->cert_x509, tls->cert_public_key );
196 3324 : tls->cert_x509_sz = FD_X509_MOCK_CERT_SZ;
197 :
198 : /* Set ALPN protocol ID
199 : (Technically, don't need to copy the length prefix but we'll do
200 : so anyways.) */
201 3324 : tls->alpn[ 0 ] = 0x0a;
202 3324 : memcpy( tls->alpn+1, "solana-tpu", 11UL );
203 3324 : tls->alpn_sz = 11UL;
204 3324 : }
205 :
206 : void *
207 3321 : fd_quic_tls_delete( fd_quic_tls_t * self ) {
208 3321 : if( FD_UNLIKELY( !self ) ) {
209 0 : FD_LOG_WARNING(( "NULL self" ));
210 0 : return NULL;
211 0 : }
212 :
213 : // free up all used handshakes
214 3321 : ulong hs_sz = (ulong)self->max_concur_handshakes;
215 3321 : fd_quic_tls_hs_t * hs = self->handshakes;
216 3321 : uchar * hs_used = self->used_handshakes;
217 19791 : for( ulong j = 0; j < hs_sz; ++j ) {
218 16470 : if( hs_used[j] ) fd_quic_tls_hs_delete( hs + j );
219 16470 : }
220 :
221 : /* Clear secret data */
222 3321 : fd_memset( &self->tls, 0, sizeof(fd_tls_t) );
223 :
224 3321 : return self;
225 3321 : }
226 :
227 : fd_quic_tls_hs_t *
228 : fd_quic_tls_hs_new( fd_quic_tls_t * quic_tls,
229 : void * context,
230 : int is_server,
231 : char const * hostname,
232 12396 : fd_quic_transport_params_t const * self_transport_params ) {
233 : // find a free handshake
234 12396 : ulong hs_idx = 0;
235 12396 : ulong hs_sz = (ulong)quic_tls->max_concur_handshakes;
236 12396 : uchar * hs_used = quic_tls->used_handshakes;
237 12399 : while( hs_idx < hs_sz && hs_used[hs_idx] ) hs_idx++;
238 :
239 : // no room
240 12396 : if( hs_idx == hs_sz ) {
241 0 : FD_DEBUG( FD_LOG_DEBUG(( "tls_hs alloc fail" )) );
242 0 : return NULL;
243 0 : }
244 :
245 12396 : FD_DEBUG( FD_LOG_DEBUG(( "tls_hs alloc %lu", hs_idx )) );
246 :
247 : // self is the handshake at hs_idx
248 12396 : fd_quic_tls_hs_t * self = quic_tls->handshakes + hs_idx;
249 12396 : FD_TEST( fd_ulong_is_aligned( (ulong)self, alignof(fd_quic_tls_hs_t) ) );
250 :
251 : // clear the handshake bits
252 12396 : fd_memset( self, 0, sizeof(fd_quic_tls_hs_t) );
253 :
254 : // set properties on self
255 12396 : self->quic_tls = quic_tls;
256 12396 : self->is_server = is_server;
257 12396 : self->is_flush = 0;
258 12396 : self->context = context;
259 12396 : self->state = FD_QUIC_TLS_HS_STATE_NEED_INPUT;
260 :
261 : /* initialize handshake data */
262 :
263 : /* init free list */
264 12396 : self->hs_data_free_idx = 0u; /* head points at first */
265 210732 : for( ushort j = 0u; j < FD_QUIC_TLS_HS_DATA_CNT; ++j ) {
266 198336 : if( j < FD_QUIC_TLS_HS_DATA_CNT-1u ) {
267 185940 : self->hs_data[j].next_idx = (ushort)(j+1u); /* each point to next */
268 185940 : } else {
269 12396 : self->hs_data[j].next_idx = FD_QUIC_TLS_HS_DATA_UNUSED ;
270 12396 : }
271 198336 : }
272 :
273 : /* no data pending */
274 61980 : for( unsigned j = 0; j < 4; ++j ) {
275 49584 : self->hs_data_pend_idx[j] = FD_QUIC_TLS_HS_DATA_UNUSED;
276 49584 : self->hs_data_pend_end_idx[j] = FD_QUIC_TLS_HS_DATA_UNUSED;
277 49584 : }
278 :
279 : /* set head and tail of used hs_data */
280 12396 : self->hs_data_buf_head = 0;
281 12396 : self->hs_data_buf_tail = 0;
282 :
283 : /* all handshake offsets start at zero */
284 12396 : fd_memset( self->hs_data_offset, 0, sizeof( self->hs_data_offset ) );
285 :
286 12396 : if( is_server ) {
287 6381 : fd_tls_estate_srv_new( &self->hs.srv );
288 6381 : } else {
289 6015 : fd_tls_estate_cli_new( &self->hs.cli );
290 6015 : }
291 :
292 : /* TODO set TLS hostname if client */
293 12396 : (void)hostname;
294 :
295 : /* Set QUIC transport params */
296 12396 : self->self_transport_params = *self_transport_params;
297 :
298 : /* Mark handshake as used */
299 12396 : hs_used[hs_idx] = 1;
300 12396 : return self;
301 12396 : }
302 :
303 : void
304 26508 : fd_quic_tls_hs_delete( fd_quic_tls_hs_t * self ) {
305 26508 : if( !self ) return;
306 :
307 12396 : self->state = FD_QUIC_TLS_HS_STATE_DEAD;
308 :
309 12396 : fd_quic_tls_t * quic_tls = self->quic_tls;
310 :
311 : // find index into array
312 12396 : ulong hs_idx = (ulong)( self - quic_tls->handshakes );
313 12396 : FD_DEBUG( FD_LOG_DEBUG(( "tls_hs free %lu", hs_idx )) );
314 12396 : if( quic_tls->used_handshakes[hs_idx] != 1 ) {
315 0 : return;
316 0 : }
317 :
318 12396 : if( self->is_server )
319 6381 : fd_tls_estate_srv_delete( &self->hs.srv );
320 6015 : else
321 6015 : fd_tls_estate_cli_delete( &self->hs.cli );
322 :
323 : // set used at the given index to zero to free
324 12396 : quic_tls->used_handshakes[hs_idx] = 0;
325 12396 : }
326 :
327 : int
328 : fd_quic_tls_provide_data( fd_quic_tls_hs_t * self,
329 : uint enc_level,
330 : uchar const * data,
331 48120 : ulong data_sz ) {
332 :
333 48120 : switch( self->state ) {
334 0 : case FD_QUIC_TLS_HS_STATE_DEAD:
335 0 : case FD_QUIC_TLS_HS_STATE_COMPLETE:
336 0 : return FD_QUIC_SUCCESS;
337 48120 : default:
338 48120 : break;
339 48120 : }
340 :
341 : /* Client needs to initiate the handshake */
342 :
343 48120 : if( ( self->hs.base.state == FD_TLS_HS_START ) &
344 48120 : ( !self->is_server ) ) {
345 6015 : long res = fd_tls_client_handshake( &self->quic_tls->tls, &self->hs.cli, NULL, 0UL, 0 );
346 6015 : if( FD_UNLIKELY( res<0L ) ) {
347 0 : self->alert = (uint)-res;
348 0 : return FD_QUIC_FAILED;
349 0 : }
350 6015 : return FD_QUIC_SUCCESS;
351 6015 : }
352 :
353 : /* QUIC-TLS allows coalescing multiple records into the same CRYPTO
354 : frame. It also allows fragmentation, but we don't support that. */
355 :
356 42105 : do {
357 42105 : long res = fd_tls_handshake( &self->quic_tls->tls, &self->hs, data, data_sz, enc_level );
358 :
359 42105 : if( FD_UNLIKELY( res<0L ) ) {
360 0 : int alert = (int)-res;
361 0 : self->alert = (uint)alert;
362 0 : return FD_QUIC_FAILED;
363 0 : }
364 42105 : if( FD_UNLIKELY( res==0UL ) ) {
365 0 : FD_LOG_WARNING(( "preventing deadlock" ));
366 0 : return FD_QUIC_FAILED;
367 0 : }
368 :
369 42105 : data += (ulong)res;
370 42105 : data_sz -= (ulong)res;
371 42105 : } while( data_sz );
372 :
373 42105 : switch( self->hs.base.state ) {
374 12030 : case FD_TLS_HS_CONNECTED:
375 : /* handshake completed */
376 12030 : self->is_hs_complete = 1;
377 12030 : self->quic_tls->handshake_complete_cb( self, self->context );
378 12030 : self->state = FD_QUIC_TLS_HS_STATE_COMPLETE;
379 12030 : return FD_QUIC_SUCCESS;
380 0 : case FD_TLS_HS_FAIL:
381 : /* handshake permanently failed */
382 0 : self->state = FD_QUIC_TLS_HS_STATE_DEAD;
383 0 : return FD_QUIC_FAILED;
384 30075 : default:
385 : /* fd_quic_tls_provide_data will perform as much handshaking as
386 : possible. Thus, we know that we are blocked on needing more data
387 : when we reach fd_quic_tls_process without having completed the
388 : handshake. */
389 30075 : self->state = FD_QUIC_TLS_HS_STATE_NEED_INPUT;
390 30075 : return FD_QUIC_SUCCESS;
391 42105 : }
392 42105 : }
393 :
394 : /* internal callbacks */
395 :
396 : int
397 : fd_quic_tls_sendmsg( void const * handshake,
398 : void const * data,
399 : ulong data_sz,
400 : uint enc_level,
401 42105 : int flush ) {
402 :
403 42105 : uint buf_sz = FD_QUIC_TLS_HS_DATA_SZ;
404 42105 : if( data_sz > buf_sz ) {
405 0 : return 0;
406 0 : }
407 :
408 : /* Safe because the fd_tls_estate_{srv,cli}_t object is the first
409 : element of fd_quic_tls_hs_t */
410 42105 : fd_quic_tls_hs_t * hs = (fd_quic_tls_hs_t *)handshake;
411 42105 : hs->is_flush |= flush;
412 :
413 : /* add handshake data to handshake for retrieval by user */
414 :
415 : /* find free handshake data */
416 42105 : ushort hs_data_idx = hs->hs_data_free_idx;
417 42105 : if( hs_data_idx == FD_QUIC_TLS_HS_DATA_UNUSED ) {
418 : /* no free structures left. fail */
419 0 : return 0;
420 0 : }
421 :
422 : /* allocate enough space from hs data buffer */
423 42105 : uint head = hs->hs_data_buf_head;
424 42105 : uint tail = hs->hs_data_buf_tail;
425 42105 : uint alloc_head = 0; /* to be determined */
426 :
427 42105 : uint alloc_data_sz = fd_uint_align_up( (uint)data_sz, FD_QUIC_TLS_HS_DATA_ALIGN );
428 42105 : uint free_data_sz = alloc_data_sz; /* the number of bytes to free */
429 :
430 : /* we need contiguous bytes
431 : head >= buf_sz implies wrap around */
432 42105 : if( head >= buf_sz ) {
433 : /* wrap around implies entire unused block is contiguous */
434 0 : if( head - tail < alloc_data_sz ) {
435 : /* not enough free */
436 0 : return 0;
437 0 : } else {
438 0 : alloc_head = head;
439 0 : }
440 42105 : } else {
441 : /* available data split */
442 42105 : if( buf_sz - head >= alloc_data_sz ) {
443 42105 : alloc_head = head;
444 42105 : } else {
445 : /* not enough at head, try front */
446 0 : if( tail < alloc_data_sz ) {
447 : /* not enough here either */
448 0 : return 0;
449 0 : }
450 :
451 : /* since we're skipping some free space at end of buffer,
452 : we need to free that also, upon pop */
453 0 : alloc_head = 0;
454 0 : free_data_sz = alloc_data_sz + buf_sz - head;
455 0 : }
456 42105 : }
457 :
458 : /* success */
459 :
460 42105 : uint buf_mask = (uint)( buf_sz - 1u );
461 42105 : fd_quic_tls_hs_data_t * hs_data = &hs->hs_data[hs_data_idx];
462 42105 : uchar * buf = &hs->hs_data_buf[alloc_head & buf_mask];
463 :
464 : /* update free list */
465 42105 : hs->hs_data_free_idx = hs_data->next_idx;
466 :
467 : /* update buffer pointers */
468 42105 : hs->hs_data_buf_head = alloc_head + alloc_data_sz;
469 :
470 : /* copy data into buffer, and update metadata in hs_data */
471 42105 : fd_memcpy( buf, data, data_sz );
472 42105 : hs_data->enc_level = enc_level;
473 42105 : hs_data->data = buf;
474 42105 : hs_data->data_sz = (uint)data_sz;
475 42105 : hs_data->free_data_sz = free_data_sz;
476 42105 : hs_data->offset = hs->hs_data_offset[enc_level];
477 :
478 : /* offset adjusted ready for more data */
479 42105 : hs->hs_data_offset[enc_level] += (uint)data_sz;
480 :
481 : /* add to end of pending list */
482 42105 : hs_data->next_idx = FD_QUIC_TLS_HS_DATA_UNUSED;
483 42105 : ulong pend_end_idx = hs->hs_data_pend_end_idx[enc_level];
484 42105 : if( pend_end_idx == FD_QUIC_TLS_HS_DATA_UNUSED ) {
485 : /* pending list is empty */
486 24060 : hs->hs_data_pend_end_idx[enc_level] = hs->hs_data_pend_idx[enc_level] = hs_data_idx;
487 24060 : } else {
488 : /* last element must point to next */
489 18045 : hs->hs_data[pend_end_idx].next_idx = hs_data_idx;
490 18045 : hs->hs_data_pend_end_idx[enc_level] = hs_data_idx;
491 18045 : }
492 :
493 42105 : return 1;
494 42105 : }
495 :
496 : void
497 : fd_quic_tls_secrets( void const * handshake,
498 : void const * recv_secret,
499 : void const * send_secret,
500 24060 : uint enc_level ) {
501 :
502 24060 : fd_quic_tls_hs_t * hs = (fd_quic_tls_hs_t *)handshake;
503 :
504 24060 : fd_quic_tls_secret_t secret = { .enc_level = enc_level };
505 24060 : memcpy( secret.read_secret, recv_secret, 32UL );
506 24060 : memcpy( secret.write_secret, send_secret, 32UL );
507 :
508 24060 : hs->quic_tls->secret_cb( hs, hs->context, &secret );
509 24060 : }
510 :
511 : fd_quic_tls_hs_data_t *
512 : fd_quic_tls_get_hs_data( fd_quic_tls_hs_t * self,
513 19562477 : uint enc_level ) {
514 19562477 : if( !self ) return NULL;
515 :
516 187644 : uint idx = self->hs_data_pend_idx[enc_level];
517 187644 : if( idx == FD_QUIC_TLS_HS_DATA_UNUSED ) return NULL;
518 :
519 102237 : return &self->hs_data[idx];
520 187644 : }
521 :
522 : fd_quic_tls_hs_data_t *
523 84174 : fd_quic_tls_get_next_hs_data( fd_quic_tls_hs_t * self, fd_quic_tls_hs_data_t * hs ) {
524 84174 : ushort idx = hs->next_idx;
525 84174 : if( idx == (ushort)(~0u) ) return NULL;
526 36072 : return self->hs_data + idx;
527 84174 : }
528 :
529 : void
530 42105 : fd_quic_tls_pop_hs_data( fd_quic_tls_hs_t * self, uint enc_level ) {
531 42105 : ushort idx = self->hs_data_pend_idx[enc_level];
532 42105 : if( idx == FD_QUIC_TLS_HS_DATA_UNUSED ) return;
533 :
534 42105 : fd_quic_tls_hs_data_t * hs_data = &self->hs_data[idx];
535 :
536 42105 : uint buf_sz = FD_QUIC_TLS_HS_DATA_SZ;
537 42105 : uint free_data_sz = hs_data->free_data_sz; /* amount of data to free */
538 :
539 : /* move tail pointer */
540 42105 : uint head = self->hs_data_buf_head;
541 42105 : uint tail = self->hs_data_buf_tail;
542 :
543 42105 : tail += free_data_sz;
544 42105 : if( tail > head ) {
545 : /* logic error - tried to free more than was allocated */
546 0 : FD_LOG_ERR(( "fd_quic_tls_pop_hs_data: tried to free more than was allocated" ));
547 0 : return;
548 0 : }
549 :
550 : /* adjust to maintain invariants */
551 42105 : if( tail >= buf_sz ) {
552 0 : tail -= buf_sz;
553 0 : head -= buf_sz;
554 0 : }
555 :
556 : /* write back head and tail */
557 42105 : self->hs_data_buf_head = head;
558 42105 : self->hs_data_buf_tail = tail;
559 :
560 : /* pop from pending list */
561 42105 : self->hs_data_pend_idx[enc_level] = hs_data->next_idx;
562 :
563 : /* if idx is the last, update last */
564 42105 : if( hs_data->next_idx == FD_QUIC_TLS_HS_DATA_UNUSED ) {
565 24060 : self->hs_data_pend_end_idx[enc_level] = FD_QUIC_TLS_HS_DATA_UNUSED;
566 24060 : }
567 :
568 42105 : }
569 :
570 : void *
571 : fd_quic_tls_rand( void * ctx,
572 : void * buf,
573 12030 : ulong bufsz ) {
574 12030 : (void)ctx;
575 12030 : FD_TEST( fd_rng_secure( buf, bufsz ) );
576 12030 : return buf;
577 12030 : }
578 :
579 : ulong
580 : fd_quic_tls_tp_self( void * const handshake,
581 : uchar * const quic_tp,
582 12030 : ulong const quic_tp_bufsz ) {
583 12030 : fd_quic_tls_hs_t * hs = (fd_quic_tls_hs_t *)handshake;
584 :
585 12030 : ulong encoded_sz = fd_quic_encode_transport_params( quic_tp, quic_tp_bufsz, &hs->self_transport_params );
586 12030 : if( FD_UNLIKELY( encoded_sz==FD_QUIC_ENCODE_FAIL ) ) {
587 0 : FD_LOG_WARNING(( "fd_quic_encode_transport_params failed" ));
588 0 : return 0UL;
589 0 : }
590 :
591 12030 : return encoded_sz;
592 12030 : }
593 :
594 : void
595 : fd_quic_tls_tp_peer( void * handshake,
596 : uchar const * quic_tp,
597 12030 : ulong quic_tp_sz ) {
598 : /* Callback issued by fd_tls. Bubble up callback to fd_quic_tls. */
599 :
600 12030 : fd_quic_tls_hs_t * hs = (fd_quic_tls_hs_t *)handshake;
601 12030 : fd_quic_tls_t * quic_tls = hs->quic_tls;
602 :
603 12030 : quic_tls->peer_params_cb( hs->context, quic_tp, quic_tp_sz );
604 12030 : }
|