LCOV - code coverage report
Current view: top level - waltz/quic/tls - fd_quic_tls.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 250 314 79.6 %
Date: 2024-11-13 11:58:15 Functions: 17 17 100.0 %

          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 : }

Generated by: LCOV version 1.14