LCOV - code coverage report
Current view: top level - disco/keyguard - fd_keyguard_authorize.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 153 0.0 %
Date: 2025-09-18 04:41:32 Functions: 0 9 0.0 %

          Line data    Source code
       1             : #include "fd_keyguard.h"
       2             : #include "fd_keyguard_client.h"
       3             : #include "../bundle/fd_bundle_crank_constants.h"
       4             : #include "../../waltz/tls/fd_tls.h"
       5             : 
       6             : struct fd_keyguard_sign_req {
       7             :   fd_keyguard_authority_t * authority;
       8             : };
       9             : 
      10             : typedef struct fd_keyguard_sign_req fd_keyguard_sign_req_t;
      11             : 
      12             : static int
      13             : fd_keyguard_authorize_vote_txn( fd_keyguard_authority_t const * authority,
      14             :                                 uchar const *                   data,
      15             :                                 ulong                           sz,
      16           0 :                                 int                             sign_type ) {
      17             :   /* FIXME Add vote transaction authorization here */
      18           0 :   (void)authority; (void)data; (void)sz; (void)sign_type;
      19           0 :   return 1;
      20           0 : }
      21             : 
      22             : static int
      23             : fd_keyguard_authorize_gossip( fd_keyguard_authority_t const * authority,
      24             :                               uchar const *                   data,
      25             :                               ulong                           sz,
      26           0 :                               int                             sign_type ) {
      27             :   /* FIXME Add gossip message authorization here */
      28           0 :   (void)authority; (void)data; (void)sz; (void)sign_type;
      29           0 :   return 1;
      30           0 : }
      31             : 
      32             : static int
      33             : fd_keyguard_authorize_bundle_crank_txn( fd_keyguard_authority_t const * authority,
      34             :                                         uchar const *                   data,
      35             :                                         ulong                           sz,
      36           0 :                                         int                             sign_type ) {
      37           0 :   static const uchar disc1[ 8 ] = { FD_BUNDLE_CRANK_DISC_INIT_TIP_DISTR };
      38           0 :   static const uchar disc2[ 8 ] = { FD_BUNDLE_CRANK_DISC_CHANGE_TIP_RCV };
      39           0 :   static const uchar disc3[ 8 ] = { FD_BUNDLE_CRANK_DISC_CHANGE_BLK_BLD };
      40             : 
      41           0 :   if( sign_type != FD_KEYGUARD_SIGN_TYPE_ED25519 ) return 0;
      42             : 
      43           0 :   (void)authority;
      44             :   /* TODO: we can check a lot more bytes */
      45           0 :   switch( sz ) {
      46           0 :     case (FD_BUNDLE_CRANK_2_SZ-65UL):
      47           0 :       return fd_memeq( data+FD_BUNDLE_CRANK_2_IX1_DISC_OFF-65UL, disc2, 8UL ) &&
      48           0 :              fd_memeq( data+FD_BUNDLE_CRANK_2_IX2_DISC_OFF-65UL, disc3, 8UL );
      49           0 :     case (FD_BUNDLE_CRANK_3_SZ-65UL):
      50           0 :       return fd_memeq( data+FD_BUNDLE_CRANK_3_IX1_DISC_OFF-65UL, disc1, 8UL ) &&
      51           0 :              fd_memeq( data+FD_BUNDLE_CRANK_3_IX2_DISC_OFF-65UL, disc2, 8UL ) &&
      52           0 :              fd_memeq( data+FD_BUNDLE_CRANK_3_IX3_DISC_OFF-65UL, disc3, 8UL );
      53           0 :     default:
      54           0 :       return 0;
      55           0 :   }
      56           0 : }
      57             : 
      58             : static int
      59             : fd_keyguard_authorize_ping( fd_keyguard_authority_t const * authority,
      60             :                             uchar const *                   data,
      61             :                             ulong                           sz,
      62           0 :                             int                             sign_type ) {
      63           0 :   (void)authority;
      64           0 :   if( sign_type != FD_KEYGUARD_SIGN_TYPE_ED25519 ) return 0;
      65           0 :   if( sz != 32 ) return 0;
      66           0 :   if( 0!=memcmp( data, "SOLANA_PING_PONG", 16 ) ) return 0;
      67           0 :   return 1;
      68           0 : }
      69             : 
      70             : static int
      71             : fd_keyguard_authorize_pong( fd_keyguard_authority_t const * authority,
      72             :                             uchar const *                   data,
      73             :                             ulong                           sz,
      74           0 :                             int                             sign_type ) {
      75           0 :   (void)authority;
      76           0 :   if( sign_type != FD_KEYGUARD_SIGN_TYPE_SHA256_ED25519 ) return 0;
      77           0 :   if( sz != 48 ) return 0;
      78           0 :   if( 0!=memcmp( data, "SOLANA_PING_PONG", 16 ) ) return 0;
      79           0 :   return 1;
      80           0 : }
      81             : 
      82             : static int
      83             : fd_keyguard_authorize_gossip_prune( fd_keyguard_authority_t const * authority,
      84             :                                     uchar const *                   data,
      85             :                                     ulong                           sz,
      86           0 :                                     int                             sign_type ) {
      87           0 :   if( FD_UNLIKELY( sign_type != FD_KEYGUARD_SIGN_TYPE_ED25519 ) ) return 0;
      88             :   /* Prune messages always begin with the node's pubkey */
      89           0 :   if( sz<40UL ) return 0;
      90           0 :   if( 0!=memcmp( authority->identity_pubkey, data, 32 ) ) return 0;
      91           0 :   return 1;
      92           0 : }
      93             : 
      94             : static int
      95             : fd_keyguard_authorize_repair( fd_keyguard_authority_t const * authority,
      96             :                               uchar const *                   data,
      97             :                               ulong                           sz,
      98           0 :                               int                             sign_type ) {
      99             : 
     100           0 :   if( sign_type != FD_KEYGUARD_SIGN_TYPE_ED25519 ) return 0;
     101           0 :   if( sz<80 ) return 0;
     102             : 
     103           0 :   uint          discriminant = fd_uint_load_4( data );
     104           0 :   uchar const * sender       = data+4;
     105             : 
     106           0 :   if( discriminant< 8 ) return 0; /* window_index is min ID */
     107           0 :   if( discriminant>11 ) return 0; /* ancestor_hashes is max ID */
     108             : 
     109           0 :   if( 0!=memcmp( authority->identity_pubkey, sender, 32 ) ) return 0;
     110             : 
     111           0 :   return 1;
     112           0 : }
     113             : 
     114             : static int
     115             : fd_keyguard_authorize_tls_cv( fd_keyguard_authority_t const * authority FD_PARAM_UNUSED,
     116             :                               uchar const *                   data,
     117             :                               ulong                           sz,
     118           0 :                               int                             sign_type ) {
     119           0 :   if( FD_UNLIKELY( sign_type != FD_KEYGUARD_SIGN_TYPE_ED25519 ) ) return 0;
     120           0 :   if( FD_UNLIKELY( sz != 130 ) ) return 0;
     121             : 
     122             :   /* validate client prefix against fd_tls */
     123           0 :   return fd_memeq( fd_tls13_cli_sign_prefix, data, sizeof(fd_tls13_cli_sign_prefix) );
     124           0 : }
     125             : 
     126             : int
     127             : fd_keyguard_payload_authorize( fd_keyguard_authority_t const * authority,
     128             :                                uchar const *                   data,
     129             :                                ulong                           sz,
     130             :                                int                             role,
     131           0 :                                int                             sign_type ) {
     132             : 
     133           0 :   if( sz > FD_KEYGUARD_SIGN_REQ_MTU ) {
     134           0 :     FD_LOG_WARNING(( "oversz signing request (role=%d sz=%lu)", role, sz ));
     135           0 :     return 0;
     136           0 :   }
     137             : 
     138             :   /* Identify payload type */
     139             : 
     140           0 :   ulong payload_mask = fd_keyguard_payload_match( data, sz, sign_type );
     141           0 :   int   match_cnt    = fd_ulong_popcnt( payload_mask );
     142           0 :   if( FD_UNLIKELY( payload_mask==0UL ) ) {
     143           0 :     FD_LOG_WARNING(( "unrecognized payload type (role=%#x)", (uint)role ));
     144           0 :   }
     145             : 
     146           0 :   int is_ambiguous = match_cnt != 1;
     147             : 
     148             :  /* We know that gossip, gossip prune, and repair messages are
     149             :     ambiguous, so allow mismatches here. */
     150           0 :   int is_gossip_repair =
     151           0 :     0==( payload_mask &
     152           0 :         (~( FD_KEYGUARD_PAYLOAD_GOSSIP |
     153           0 :             FD_KEYGUARD_PAYLOAD_REPAIR |
     154           0 :             FD_KEYGUARD_PAYLOAD_PRUNE  ) ) );
     155             :   /* Also allow ambiguities between shred and gossip ping messages
     156             :      until shred sign type is fixed... */
     157           0 :   int is_shred_ping =
     158           0 :     0==( payload_mask &
     159           0 :         (~( FD_KEYGUARD_PAYLOAD_SHRED |
     160           0 :             FD_KEYGUARD_PAYLOAD_PING  ) ) );
     161             : 
     162           0 :   if( FD_UNLIKELY( is_ambiguous && !is_gossip_repair && !is_shred_ping ) ) {
     163           0 :     FD_LOG_WARNING(( "ambiguous payload type (role=%#x mask=%#lx)", (uint)role, payload_mask ));
     164           0 :   }
     165             : 
     166             :   /* Authorize each role */
     167             : 
     168           0 :   switch( role ) {
     169             : 
     170           0 :   case FD_KEYGUARD_ROLE_SEND: {
     171           0 :     int txn_ok = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_TXN )) &&
     172           0 :                  fd_keyguard_authorize_vote_txn( authority, data, sz, sign_type );
     173           0 :     int tls_ok = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_TLS_CV )) &&
     174           0 :                  fd_keyguard_authorize_tls_cv( authority, data, sz, sign_type );
     175           0 :     if( FD_UNLIKELY( !txn_ok && !tls_ok ) ) {
     176           0 :       FD_LOG_WARNING(( "unauthorized payload type for send (mask=%#lx)", payload_mask ));
     177           0 :       return 0;
     178           0 :     }
     179           0 :     return 1;
     180           0 :   }
     181             : 
     182           0 :   case FD_KEYGUARD_ROLE_GOSSIP: {
     183           0 :     int ping_ok   = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_PING )) &&
     184           0 :                     fd_keyguard_authorize_ping( authority, data, sz, sign_type );
     185           0 :     int pong_ok   = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_PONG )) &&
     186           0 :                     fd_keyguard_authorize_pong( authority, data, sz, sign_type );
     187           0 :     int prune_ok  = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_PRUNE )) &&
     188           0 :                     fd_keyguard_authorize_gossip_prune( authority, data, sz, sign_type );
     189           0 :     int gossip_ok = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_GOSSIP )) &&
     190           0 :                     fd_keyguard_authorize_gossip( authority, data, sz, sign_type );
     191           0 :     if( FD_UNLIKELY( !ping_ok && !pong_ok && !prune_ok && !gossip_ok ) ) {
     192           0 :       FD_LOG_WARNING(( "unauthorized payload type for gossip (mask=%#lx)", payload_mask ));
     193           0 :       return 0;
     194           0 :     }
     195           0 :     return 1;
     196           0 :   }
     197             : 
     198           0 :   case FD_KEYGUARD_ROLE_REPAIR: {
     199           0 :     int ping_ok   = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_PING )) &&
     200           0 :                     fd_keyguard_authorize_ping( authority, data, sz, sign_type );
     201           0 :     int pong_ok   = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_PONG )) &&
     202           0 :                     fd_keyguard_authorize_pong( authority, data, sz, sign_type );
     203           0 :     int repair_ok = (!!( payload_mask & FD_KEYGUARD_PAYLOAD_REPAIR )) &&
     204           0 :                     fd_keyguard_authorize_repair( authority, data, sz, sign_type );
     205           0 :     if( FD_UNLIKELY( !ping_ok && !pong_ok && !repair_ok ) ) {
     206           0 :       FD_LOG_WARNING(( "unauthorized payload type for repair (mask=%#lx)", payload_mask ));
     207           0 :       return 0;
     208           0 :     }
     209           0 :     return 1;
     210           0 :   }
     211             : 
     212           0 :   case FD_KEYGUARD_ROLE_LEADER:
     213           0 :     if( FD_UNLIKELY( payload_mask != FD_KEYGUARD_PAYLOAD_SHRED ) ) {
     214           0 :       FD_LOG_WARNING(( "unauthorized payload type for leader (mask=%#lx)", payload_mask ));
     215           0 :       return 0;
     216           0 :     }
     217             :     /* no further restrictions on shred */
     218           0 :     return 1;
     219             : 
     220           0 :   case FD_KEYGUARD_ROLE_BUNDLE:
     221           0 :     if( FD_UNLIKELY( payload_mask != FD_KEYGUARD_PAYLOAD_BUNDLE ) ) {
     222           0 :       FD_LOG_WARNING(( "unauthorized payload type for bundle (mask=%#lx)", payload_mask ));
     223           0 :       return 0;
     224           0 :     }
     225             :     /* no further restrictions on bundle */
     226           0 :     return 1;
     227             : 
     228           0 :   case FD_KEYGUARD_ROLE_EVENT:
     229           0 :     if( FD_UNLIKELY( payload_mask != FD_KEYGUARD_PAYLOAD_EVENT ) ) {
     230           0 :       FD_LOG_WARNING(( "unauthorized payload type for event (mask=%#lx)", payload_mask ));
     231           0 :       return 0;
     232           0 :     }
     233             :     /* no further restrictions on event */
     234           0 :     return 1;
     235             : 
     236           0 :   case FD_KEYGUARD_ROLE_BUNDLE_CRANK:
     237           0 :     if( FD_UNLIKELY( payload_mask != FD_KEYGUARD_PAYLOAD_TXN ) ) {
     238           0 :       FD_LOG_WARNING(( "unauthorized payload type for event (mask=%#lx)", payload_mask ));
     239           0 :       return 0;
     240           0 :     }
     241           0 :     return fd_keyguard_authorize_bundle_crank_txn( authority, data, sz, sign_type );
     242             : 
     243           0 :   default:
     244           0 :     FD_LOG_WARNING(( "unsupported role=%#x", (uint)role ));
     245           0 :     return 0;
     246           0 :   }
     247           0 : }

Generated by: LCOV version 1.14