Line data Source code
1 : #if !FD_HAS_HOSTED
2 : #error "This target requires FD_HAS_HOSTED"
3 : #endif
4 :
5 : /* fuzz_tls parses fd_tls handshaking. The first few bytes are used as
6 : entropy to reconstruct a fake state. */
7 :
8 : #include "fd_tls.h"
9 : #include "fd_tls_estate.h"
10 : #include "test_tls_helper.h"
11 : #include "../../ballet/ed25519/fd_ed25519.h"
12 : #include "../../ballet/ed25519/fd_x25519.h"
13 : #include "../../ballet/x509/fd_x509_mock.h"
14 :
15 : #include <assert.h>
16 : #include <stdlib.h>
17 :
18 : static void
19 : _tls_secrets( void const * handshake,
20 : void const * recv_secret,
21 : void const * send_secret,
22 0 : uint encryption_level ) {
23 0 : (void)handshake;
24 0 : (void)recv_secret;
25 0 : (void)send_secret;
26 0 : (void)encryption_level;
27 0 : }
28 :
29 : static int
30 : _tls_sendmsg( void const * handshake,
31 : void const * record,
32 : ulong record_sz,
33 : uint encryption_level,
34 0 : int flush ) {
35 0 : (void)handshake;
36 0 : (void)record;
37 0 : (void)record_sz;
38 0 : (void)encryption_level;
39 0 : (void)flush;
40 0 : return 1;
41 0 : }
42 :
43 : static ulong
44 : _tls_quic_tp_self( void * handshake,
45 : uchar * quic_tp,
46 0 : ulong quic_tp_bufsz ) {
47 0 : (void)handshake;
48 0 : static uchar const tp_buf[] = { 0x01, 0x02, 0x47, 0xd0 };
49 0 : assert( quic_tp_bufsz >= sizeof(tp_buf) );
50 0 : fd_memcpy( quic_tp, tp_buf, sizeof(tp_buf) );
51 0 : return sizeof(tp_buf);
52 0 : }
53 :
54 : static void
55 : _tls_quic_tp_peer( void * handshake,
56 : uchar const * quic_tp,
57 0 : ulong quic_tp_sz ) {
58 0 : (void)handshake;
59 0 : (void)quic_tp;
60 0 : (void)quic_tp_sz;
61 0 : }
62 :
63 : static fd_tls_t tls_tmpl[1] = {{
64 : .secrets_fn = _tls_secrets,
65 : .sendmsg_fn = _tls_sendmsg,
66 : .quic_tp_self_fn = _tls_quic_tp_self,
67 : .quic_tp_peer_fn = _tls_quic_tp_peer,
68 :
69 : .alpn = "\xasolana-tpu",
70 : .alpn_sz = 11U,
71 : }};
72 :
73 : int
74 : LLVMFuzzerInitialize( int * argc,
75 : char *** argv ) {
76 : /* Set up shell without signal handlers */
77 : putenv( "FD_LOG_BACKTRACE=0" );
78 : fd_boot( argc, argv );
79 : atexit( fd_halt );
80 :
81 : fd_rng_t _rng[1]; fd_rng_t * rng = fd_rng_join( fd_rng_new( _rng, 1000U, 0UL ) );
82 :
83 : for( ulong b=0; b<32UL; b++ ) tls_tmpl->kex_private_key[b] = fd_rng_uchar( rng );
84 : fd_x25519_public( tls_tmpl->kex_public_key, tls_tmpl->kex_private_key );
85 :
86 : fd_tls_test_sign_ctx_t sign_ctx = fd_tls_test_sign_ctx( rng );
87 : tls_tmpl->sign = fd_tls_test_sign( &sign_ctx );
88 : fd_memcpy( tls_tmpl->cert_public_key, sign_ctx.public_key, 32UL );
89 : fd_x509_mock_cert( tls_tmpl->cert_x509, tls_tmpl->cert_public_key );
90 : tls_tmpl->cert_x509_sz = FD_X509_MOCK_CERT_SZ;
91 :
92 : fd_rng_delete( fd_rng_leave( rng ) );
93 : return 0;
94 : }
95 :
96 : /* Could be a bitmap */
97 :
98 : static uchar
99 : _tls_valid_srv_hs_state[ 16 ] = {
100 : [FD_TLS_HS_FAIL ] = 1,
101 : [FD_TLS_HS_CONNECTED ] = 1,
102 : [FD_TLS_HS_START ] = 1,
103 : [FD_TLS_HS_WAIT_CERT ] = 1,
104 : [FD_TLS_HS_WAIT_CV ] = 1,
105 : [FD_TLS_HS_WAIT_FINISHED] = 1
106 : };
107 :
108 : static uchar
109 : _tls_valid_cli_hs_state[ 16 ] = {
110 : [FD_TLS_HS_FAIL ] = 1,
111 : [FD_TLS_HS_CONNECTED ] = 1,
112 : [FD_TLS_HS_START ] = 1,
113 : [FD_TLS_HS_WAIT_SH ] = 1,
114 : [FD_TLS_HS_WAIT_EE ] = 1,
115 : [FD_TLS_HS_WAIT_CERT_CR ] = 1,
116 : [FD_TLS_HS_WAIT_CERT ] = 1,
117 : [FD_TLS_HS_WAIT_CV ] = 1,
118 : [FD_TLS_HS_WAIT_FINISHED] = 1
119 : };
120 :
121 : int
122 : LLVMFuzzerTestOneInput( uchar const * input,
123 : ulong input_sz ) {
124 :
125 : fd_rng_t _rng[1]; fd_rng_t * rng = fd_rng_join( fd_rng_new( _rng, 1001U, 0UL ) );
126 :
127 : if( input_sz<8UL ) return -1;
128 : ulong state = FD_LOAD( ulong, input );
129 :
130 : uchar const * payload = input + 8UL;
131 : ulong payload_sz = input_sz - 8UL;
132 :
133 : int is_server = !!( state & (1UL<< 0) );
134 : int has_alpn = !!( state & (1UL<< 1) );
135 : int has_x509 = !!( state & (1UL<< 2) );
136 : int is_quic = !!( state & (1UL<< 3) );
137 : uchar hs_state = (uchar)( ( state>> 4 )&0xFUL );
138 : int srv_rpk = !!( state & (1UL<< 8) );
139 : int cli_rpk = !!( state & (1UL<< 9) );
140 : int cli_cert = !!( state & (1UL<<10) );
141 : uint enc_lvl = (uint)( ( state>>11 )&0x3UL );
142 :
143 : fd_tls_t tls[1]; fd_memcpy( tls, tls_tmpl, sizeof(fd_tls_t) );
144 : tls->rand = fd_tls_test_rand( rng );
145 : tls->quic = (uchar)(is_quic&1);
146 : if( !has_alpn ) tls->alpn_sz = 0UL;
147 : if( !has_x509 ) tls->cert_x509_sz = 0UL;
148 :
149 : fd_tls_estate_base_t base = {
150 : .state = hs_state,
151 : .server = (uchar)( is_server&1 ),
152 : };
153 : for( ulong b=0; b<32UL; b++ ) base.client_random[b] = fd_rng_uchar( rng );
154 :
155 : if( is_server ) {
156 : if( !_tls_valid_srv_hs_state[ hs_state ] ) return -1;
157 : fd_tls_estate_srv_t hs[1] = {{
158 : .base = base,
159 : .server_cert_rpk = (uchar)(srv_rpk &1),
160 : .client_cert = (uchar)(cli_cert&1),
161 : .client_cert_rpk = (uchar)(cli_rpk &1),
162 : }};
163 : fd_tls_server_handshake( tls, hs, payload, payload_sz, enc_lvl );
164 : } else {
165 : if( !_tls_valid_cli_hs_state[ hs_state ] ) return -1;
166 : fd_tls_estate_cli_t hs[1] = {{
167 : .base = base,
168 : .server_cert_rpk = (uchar)(srv_rpk &1),
169 : .client_cert = (uchar)(cli_cert&1),
170 : .client_cert_rpk = (uchar)(cli_rpk &1),
171 : }};
172 : fd_tls_client_handshake( tls, hs, payload, payload_sz, enc_lvl );
173 : }
174 :
175 : fd_rng_delete( fd_rng_leave( rng ) );
176 : return 0;
177 : }
|