Line data Source code
1 : #include "fd_tls.h"
2 : #include "fd_tls_proto.h"
3 : #include "../../ballet/ed25519/fd_ed25519.h"
4 : #include "../../ballet/ed25519/fd_x25519.h"
5 : #include "../../ballet/hmac/fd_hmac.h"
6 :
7 : /* Pre-generated keys */
8 :
9 : char const fd_tls13_cli_sign_prefix[ 98 ] =
10 : " " /* 32 spaces */
11 : " " /* 32 spaces */
12 : "TLS 1.3, client CertificateVerify";
13 :
14 : static char const fd_tls13_srv_sign_prefix[ 98 ] =
15 : " " /* 32 spaces */
16 : " " /* 32 spaces */
17 : "TLS 1.3, server CertificateVerify";
18 :
19 : //uchar empty_hash[ 32 ];
20 : //fd_sha256_hash( empty_hash, NULL, 0UL );
21 : static uchar const empty_hash[ 32 ] =
22 : { 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
23 : 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
24 : 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
25 : 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 };
26 :
27 : //static uchar const psk[ 32 ] = {0};
28 : //uchar early_secret[ 32 ];
29 : //fd_hmac_sha256( /* data */ psk, 32UL,
30 : // /* salt */ NULL, 0UL,
31 : // early_secret );
32 : //static uchar const early_secret[ 32 ] =
33 : // { 0x33, 0xad, 0x0a, 0x1c, 0x60, 0x7e, 0xc0, 0x3b,
34 : // 0x09, 0xe6, 0xcd, 0x98, 0x93, 0x68, 0x0c, 0xe2,
35 : // 0x10, 0xad, 0xf3, 0x00, 0xaa, 0x1f, 0x26, 0x60,
36 : // 0xe1, 0xb2, 0x2e, 0x10, 0xf1, 0x70, 0xf9, 0x2a };
37 :
38 : //uchar handshake_derived[ 32 ];
39 : //fd_tls_hkdf_expand_label( handshake_derived,
40 : // early_secret,
41 : // "derived", 7UL,
42 : // empty_hash, 32UL );
43 : static uchar const handshake_derived[ 32 ] =
44 : { 0x6f, 0x26, 0x15, 0xa1, 0x08, 0xc7, 0x02, 0xc5,
45 : 0x67, 0x8f, 0x54, 0xfc, 0x9d, 0xba, 0xb6, 0x97,
46 : 0x16, 0xc0, 0x76, 0x18, 0x9c, 0x48, 0x25, 0x0c,
47 : 0xeb, 0xea, 0xc3, 0x57, 0x6c, 0x36, 0x11, 0xba };
48 :
49 : /* fd_tls_t boilerplate */
50 :
51 : ulong
52 213 : fd_tls_align( void ) {
53 213 : return alignof(fd_tls_t);
54 213 : }
55 :
56 : ulong
57 213 : fd_tls_footprint( void ) {
58 213 : return sizeof(fd_tls_t);
59 213 : }
60 :
61 : void *
62 213 : fd_tls_new( void * mem ) {
63 :
64 213 : if( FD_UNLIKELY( !mem ) ) {
65 0 : FD_LOG_WARNING(( "NULL mem" ));
66 0 : return NULL;
67 0 : }
68 :
69 213 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, fd_tls_align() ) ) ) {
70 0 : FD_LOG_WARNING(( "unaligned mem" ));
71 0 : return NULL;
72 0 : }
73 :
74 213 : ulong fp = fd_tls_footprint();
75 213 : memset( mem, 0, fp );
76 213 : return mem;
77 213 : }
78 :
79 : fd_tls_t *
80 36 : fd_tls_join( void * mem ) {
81 36 : return (fd_tls_t *)mem;
82 36 : }
83 :
84 : void *
85 36 : fd_tls_leave( fd_tls_t * server ) {
86 36 : return (void *)server;
87 36 : }
88 :
89 : void *
90 36 : fd_tls_delete( void * mem ) {
91 36 : return mem;
92 36 : }
93 :
94 : /* TODO create internal state machine and integrate Tango for
95 : accelerating cryptographic computations (e.g. FPGA sigverify) */
96 :
97 : fd_tls_estate_srv_t *
98 6093 : fd_tls_estate_srv_new( void * mem ) {
99 :
100 6093 : fd_tls_estate_srv_t * hs = mem;
101 :
102 6093 : memset( hs, 0, sizeof(fd_tls_estate_srv_t) );
103 6093 : hs->base.state = FD_TLS_HS_START;
104 6093 : hs->base.server = 1;
105 :
106 6093 : return hs;
107 6093 : }
108 :
109 : fd_tls_estate_cli_t *
110 6126 : fd_tls_estate_cli_new( void * mem ) {
111 :
112 6126 : fd_tls_estate_cli_t * hs = mem;
113 :
114 6126 : memset( hs, 0, sizeof(fd_tls_estate_cli_t) );
115 6126 : hs->base.state = FD_TLS_HS_START;
116 :
117 6126 : return hs;
118 6126 : }
119 :
120 : void *
121 : fd_tls_hkdf_expand_label( uchar * out,
122 : ulong out_sz,
123 : uchar const secret[ 32 ],
124 : char const * label,
125 : ulong label_sz,
126 : uchar const * context,
127 401634 : ulong context_sz ) {
128 :
129 401634 : # define LABEL_BUFSZ (64UL)
130 401634 : FD_TEST( label_sz <=LABEL_BUFSZ );
131 401634 : FD_TEST( context_sz<=LABEL_BUFSZ );
132 401634 : FD_TEST( out_sz <=32UL );
133 :
134 : /* Create HKDF info */
135 401634 : uchar info[ 2+1+6+LABEL_BUFSZ+1+LABEL_BUFSZ+1 ];
136 401634 : ulong info_sz = 0UL;
137 :
138 : /* Length of hash output */
139 401634 : info[0]=0; info[1]=(uchar)out_sz;
140 401634 : info_sz += 2UL;
141 :
142 : /* Length prefix of label */
143 401634 : info[ info_sz ] = (uchar)( 6UL + label_sz );
144 401634 : info_sz += 1UL;
145 :
146 : /* Label */
147 401634 : memcpy( info+info_sz, "tls13 ", 6UL );
148 401634 : info_sz += 6UL;
149 401634 : memcpy( info+info_sz, label, label_sz );
150 401634 : info_sz += label_sz;
151 :
152 : /* Length prefix of context */
153 401634 : info[ info_sz ] = (uchar)( context_sz );
154 401634 : info_sz += 1UL;
155 :
156 : /* Context */
157 401634 : fd_memcpy( info+info_sz, context, context_sz );
158 401634 : info_sz += context_sz;
159 :
160 : /* HKDF-Expand suffix */
161 401634 : info[ info_sz ] = 0x01;
162 401634 : info_sz += 1UL;
163 :
164 : /* Compute result of HKDF-Expand-Label */
165 401634 : uchar hash[ 32 ];
166 401634 : fd_hmac_sha256( info, info_sz, secret, 32UL, hash );
167 401634 : fd_memcpy( out, hash, out_sz );
168 401634 : return out;
169 401634 : # undef LABEL_BUFSZ
170 401634 : }
171 :
172 : static int
173 : fd_tls_has_alpn( uchar const * list,
174 : ulong const list_sz,
175 : uchar const * target,
176 6081 : ulong const target_sz ) {
177 6081 : if( FD_UNLIKELY( target_sz<=1UL ) ) return 0;
178 :
179 6081 : uchar const * list_end = list + list_sz;
180 6081 : while( list < list_end ) {
181 6081 : ulong ele_sz = list[0];
182 6081 : list += 1UL;
183 6081 : uchar const * ele = list;
184 6081 : if( FD_UNLIKELY( (long)ele_sz > list_end-list ) ) return -1;
185 6081 : list += ele_sz;
186 :
187 6081 : if( ele_sz==target_sz-1UL )
188 6081 : if( 0==memcmp( ele, target+1UL, ele_sz ) )
189 6081 : return 1;
190 6081 : }
191 0 : return 0;
192 6081 : }
193 :
194 : /* fd_tls_alert is a convenience function for setting a handshake
195 : failure alert and reason code. */
196 :
197 : static inline long __attribute__((warn_unused_result))
198 : fd_tls_alert( fd_tls_estate_base_t * hs,
199 : uint alert,
200 21 : ushort reason ) {
201 21 : hs->reason = reason;
202 21 : return -(long)alert;
203 21 : }
204 :
205 : /* fd_tls_send_cert_verify generates and sends a CertificateVerify
206 : message. Returns 0L on success and negated TLS alert number on
207 : failure. this is the local client or server object. hs is the
208 : local handshake object. transcript is the SHA state of the
209 : transcript hasher immediately preceding the CertificateVerify (where
210 : last entry is Certificate). is_client is 1 if the local role is a
211 : client, 0 otherwise. */
212 :
213 : static long
214 : fd_tls_send_cert_verify( fd_tls_t const * this,
215 : fd_tls_estate_base_t * hs,
216 : fd_sha256_t * transcript,
217 12159 : int is_client ) {
218 :
219 : /* Export current transcript hash
220 : And create message to be signed */
221 :
222 12159 : uchar sign_msg[ 130 ];
223 12159 : fd_memcpy( sign_msg,
224 12159 : is_client ? fd_tls13_cli_sign_prefix : fd_tls13_srv_sign_prefix,
225 12159 : 98UL );
226 :
227 12159 : fd_sha256_t transcript_clone = *transcript;
228 12159 : fd_sha256_fini( &transcript_clone, sign_msg+98 );
229 :
230 : /* Sign certificate */
231 :
232 12159 : uchar cert_verify_sig[ 64UL ];
233 12159 : fd_tls_sign( &this->sign, cert_verify_sig, sign_msg );
234 :
235 : /* Create CertificateVerify message */
236 :
237 12159 : # define MSG_BUFSZ (512UL)
238 12159 : uchar msg_buf[ MSG_BUFSZ ];
239 :
240 12159 : ulong cv_sz;
241 :
242 12159 : do {
243 12159 : uchar * wire = msg_buf;
244 12159 : uchar * const wire_end = msg_buf + MSG_BUFSZ;
245 :
246 : /* Leave space for message header */
247 :
248 12159 : void * hdr_ptr = wire;
249 12159 : wire += sizeof(fd_tls_msg_hdr_t);
250 12159 : fd_tls_msg_hdr_t hdr = { .type = FD_TLS_MSG_CERT_VERIFY };
251 :
252 : /* Construct CertificateVerify */
253 :
254 12159 : fd_tls_cert_verify_t cv = {
255 12159 : .sig_alg = FD_TLS_SIGNATURE_ED25519
256 12159 : };
257 12159 : fd_memcpy( cv.sig, cert_verify_sig, 64UL );
258 :
259 : /* Encode CertificateVerify */
260 :
261 12159 : long encode_res = fd_tls_encode_cert_verify( &cv, wire, (ulong)(wire_end-wire) );
262 12159 : if( FD_UNLIKELY( encode_res<0L ) )
263 0 : return fd_tls_alert( hs, (uint)(-encode_res), FD_TLS_REASON_CV_ENCODE );
264 12159 : wire += (ulong)encode_res;
265 :
266 12159 : hdr.sz = fd_uint_to_tls_u24( (uint)encode_res );
267 12159 : fd_tls_encode_msg_hdr( &hdr, hdr_ptr, sizeof(fd_tls_msg_hdr_t) );
268 12159 : cv_sz = (ulong)(wire - msg_buf);
269 12159 : } while(0);
270 :
271 : /* Send CertificateVerify message */
272 :
273 12159 : if( FD_UNLIKELY( !this->sendmsg_fn(
274 12159 : hs,
275 12159 : msg_buf, cv_sz,
276 12159 : FD_TLS_LEVEL_HANDSHAKE,
277 12159 : /* flush */ 0 ) ) )
278 0 : return fd_tls_alert( hs, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_SENDMSG_FAIL );
279 :
280 : /* Record CertificateVerify in transcript hash */
281 :
282 12159 : fd_sha256_append( transcript, msg_buf, cv_sz );
283 :
284 12159 : # undef MSG_BUFSZ
285 12159 : return 0L;
286 12159 : }
287 :
288 : static long fd_tls_server_hs_start ( fd_tls_t const *, fd_tls_estate_srv_t *, uchar const *, ulong, uint );
289 : static long fd_tls_server_hs_wait_cert ( fd_tls_t const *, fd_tls_estate_srv_t *, uchar const *, ulong, uint );
290 : static long fd_tls_server_hs_wait_cert_verify( fd_tls_t const *, fd_tls_estate_srv_t *, uchar const *, ulong, uint );
291 : static long fd_tls_server_hs_wait_finished ( fd_tls_t const *, fd_tls_estate_srv_t *, uchar const *, ulong, uint );
292 :
293 : long
294 : fd_tls_server_handshake( fd_tls_t const * server,
295 : fd_tls_estate_srv_t * handshake,
296 : void const * msg,
297 : ulong msg_sz,
298 24333 : uint encryption_level ) {
299 24333 : switch( handshake->base.state ) {
300 6090 : case FD_TLS_HS_START:
301 6090 : return fd_tls_server_hs_start ( server, handshake, msg, msg_sz, encryption_level );
302 6081 : case FD_TLS_HS_WAIT_CERT:
303 6081 : return fd_tls_server_hs_wait_cert ( server, handshake, msg, msg_sz, encryption_level );
304 6081 : case FD_TLS_HS_WAIT_CV:
305 6081 : return fd_tls_server_hs_wait_cert_verify( server, handshake, msg, msg_sz, encryption_level );
306 6081 : case FD_TLS_HS_WAIT_FINISHED:
307 6081 : return fd_tls_server_hs_wait_finished ( server, handshake, msg, msg_sz, encryption_level );
308 0 : default:
309 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_ILLEGAL_STATE );
310 24333 : }
311 24333 : }
312 :
313 : static long
314 : fd_tls_server_hs_retry( fd_tls_t const * server,
315 : fd_tls_estate_srv_t * handshake,
316 : fd_tls_client_hello_t const * ch,
317 3 : uchar const ch1_hash[32] ) {
318 :
319 3 : if( FD_UNLIKELY( handshake->hello_retry ) ) {
320 : /* Already retried but still no X25519 share */
321 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_ILLEGAL_PARAMETER, FD_TLS_REASON_SENDMSG_FAIL );
322 0 : }
323 3 : handshake->hello_retry = 1;
324 :
325 : /* Message buffer */
326 3 : # define MSG_BUFSZ 512UL
327 3 : uchar msg_buf[ MSG_BUFSZ ];
328 :
329 : /* Transcript hasher (RetryHelloRequest variation)
330 : https://datatracker.ietf.org/doc/html/rfc8446#section-4.4.1 */
331 3 : fd_sha256_t transcript; fd_sha256_init( &transcript );
332 3 : uchar const transcript_prefix[] = { 254, 0x00, 0x00, 32 };
333 3 : fd_sha256_append( &transcript, transcript_prefix, sizeof(transcript_prefix) );
334 3 : fd_sha256_append( &transcript, ch1_hash, 32 );
335 :
336 : /* Create HelloRetryRequest message */
337 :
338 3 : ulong server_hello_sz;
339 :
340 3 : do {
341 3 : uchar * wire = msg_buf;
342 3 : uchar * const wire_end = msg_buf + MSG_BUFSZ;
343 :
344 : /* Leave space for message header */
345 :
346 3 : void * hdr_ptr = wire;
347 3 : wire += sizeof(fd_tls_msg_hdr_t);
348 3 : fd_tls_msg_hdr_t hdr = { .type = FD_TLS_MSG_SERVER_HELLO };
349 :
350 : /* Construct server hello */
351 :
352 3 : fd_tls_server_hello_t sh = {
353 3 : .cipher_suite = FD_TLS_CIPHER_SUITE_AES_128_GCM_SHA256,
354 3 : .key_share = { .has_x25519 = 1 },
355 3 : .session_id = ch->session_id,
356 3 : };
357 3 : memcpy( sh.key_share.x25519, server->kex_public_key, 32UL );
358 :
359 : /* Encode server hello */
360 :
361 3 : long encode_res = fd_tls_encode_hello_retry_request( &sh, wire, (ulong)(wire_end-wire) );
362 3 : if( FD_UNLIKELY( encode_res<0L ) )
363 0 : return fd_tls_alert( &handshake->base, (uint)(-encode_res), FD_TLS_REASON_SH_ENCODE );
364 3 : wire += (ulong)encode_res;
365 :
366 3 : hdr.sz = fd_uint_to_tls_u24( (uint)encode_res );
367 3 : fd_tls_encode_msg_hdr( &hdr, hdr_ptr, sizeof(fd_tls_msg_hdr_t) );
368 3 : server_hello_sz = (ulong)(wire - msg_buf);
369 3 : } while(0);
370 :
371 : /* Call back with HelloRetryRequest */
372 :
373 3 : if( FD_UNLIKELY( !server->sendmsg_fn(
374 3 : handshake,
375 3 : msg_buf, server_hello_sz,
376 3 : FD_TLS_LEVEL_INITIAL,
377 3 : /* flush */ 1 ) ) )
378 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_SENDMSG_FAIL );
379 :
380 : /* Record HelloRetryRequest in transcript hash */
381 :
382 3 : fd_sha256_append( &transcript, msg_buf, server_hello_sz );
383 :
384 : /* Finish up ********************************************************/
385 :
386 : /* Store transcript hash state */
387 :
388 3 : fd_tls_transcript_store( &handshake->transcript, &transcript );
389 :
390 : /* Done */
391 :
392 3 : handshake->base.state = FD_TLS_HS_START;
393 :
394 3 : # undef MSG_BUFSZ
395 3 : return (long)0L;
396 3 : }
397 :
398 : /* fd_tls_server_hs_start is invoked in response to the initial
399 : ClientHello. We send back several messages in response, including
400 : - the ServerHello, completing cryptographic negotiation
401 : - EncryptedExtensions, for further handshake data
402 : - Finished, completing the server's handshake message sequence */
403 :
404 : static long
405 : fd_tls_server_hs_start( fd_tls_t const * const server,
406 : fd_tls_estate_srv_t * const handshake,
407 : uchar const * const record,
408 : ulong record_sz,
409 6090 : uint encryption_level ) {
410 :
411 : /* Request QUIC transport params */
412 6090 : uchar quic_tp[ FD_TLS_EXT_QUIC_PARAMS_SZ_MAX ];
413 6090 : long quic_tp_sz = -1L;
414 6090 : if( server->quic )
415 6084 : quic_tp_sz = (long)server->quic_tp_self_fn( handshake, quic_tp, FD_TLS_EXT_QUIC_PARAMS_SZ_MAX );
416 6090 : if( FD_UNLIKELY( quic_tp_sz > (long)FD_TLS_EXT_QUIC_PARAMS_SZ_MAX ) )
417 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_DECODE_ERROR, FD_TLS_REASON_QUIC_TP_OVERSZ );
418 :
419 6090 : if( FD_UNLIKELY( encryption_level != FD_TLS_LEVEL_INITIAL ) )
420 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_WRONG_ENC_LVL );
421 :
422 : /* Message buffer */
423 18243 : # define MSG_BUFSZ 512UL
424 6090 : uchar msg_buf[ MSG_BUFSZ ];
425 :
426 : /* Transcript hasher */
427 6090 : fd_sha256_t transcript;
428 6090 : if( handshake->hello_retry ) {
429 3 : fd_tls_transcript_load( &handshake->transcript, &transcript );
430 6087 : } else {
431 6087 : fd_sha256_init( &transcript );
432 6087 : }
433 :
434 : /* Read client hello ************************************************/
435 :
436 6090 : fd_tls_client_hello_t ch = {0};
437 :
438 6090 : ulong read_sz;
439 6090 : do {
440 6090 : uchar const * wire = record;
441 6090 : uchar const * const wire_end = record + record_sz;
442 :
443 : /* Decode message header */
444 :
445 6090 : fd_tls_msg_hdr_t msg_hdr = {0};
446 6090 : long decode_res = fd_tls_decode_msg_hdr( &msg_hdr, wire, (ulong)(wire_end-wire) );
447 6090 : if( FD_UNLIKELY( decode_res<0L ) )
448 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_DECODE_ERROR, FD_TLS_REASON_CH_PARSE );
449 6090 : wire += (ulong)decode_res;
450 :
451 6090 : if( FD_UNLIKELY( msg_hdr.type != FD_TLS_MSG_CLIENT_HELLO ) )
452 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_UNEXPECTED_MESSAGE, FD_TLS_REASON_CH_EXPECTED );
453 :
454 : /* Decode Client Hello */
455 :
456 6090 : decode_res = fd_tls_decode_client_hello( &ch, wire, (ulong)(wire_end-wire) );
457 6090 : if( FD_UNLIKELY( decode_res<0L ) )
458 0 : return fd_tls_alert( &handshake->base, (uint)(-decode_res), FD_TLS_REASON_CH_PARSE );
459 6090 : wire += (ulong)decode_res;
460 :
461 6090 : read_sz = (ulong)(wire - record);
462 6090 : } while(0);
463 :
464 : /* Check for cryptographic compatibility */
465 :
466 6090 : if( FD_UNLIKELY( !ch.supported_versions.tls13 ) )
467 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_HANDSHAKE_FAILURE, FD_TLS_REASON_CH_NEG_VER );
468 6090 : if( FD_UNLIKELY( !ch.supported_groups.x25519 ) )
469 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_HANDSHAKE_FAILURE, FD_TLS_REASON_CH_NEG_KX );
470 6090 : if( FD_UNLIKELY( !ch.signature_algorithms.ed25519 ) )
471 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_HANDSHAKE_FAILURE, FD_TLS_REASON_CH_NEG_SIG );
472 6090 : if( FD_UNLIKELY( !ch.cipher_suites.aes_128_gcm_sha256 ) )
473 3 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_HANDSHAKE_FAILURE, FD_TLS_REASON_CH_NEG_CIPHER );
474 :
475 : /* Remember client random for SSLKEYLOGFILE */
476 6087 : fd_memcpy( handshake->base.client_random, ch.random, 32UL );
477 :
478 : /* Detect QUIC */
479 :
480 6087 : if( server->quic ) {
481 : /* QUIC transport parameters are mandatory in QUIC mode */
482 6084 : if( FD_UNLIKELY( !ch.quic_tp.buf ) )
483 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_MISSING_EXTENSION, FD_TLS_REASON_CH_NO_QUIC );
484 :
485 : /* Inform user of peer's QUIC transport parameters */
486 6084 : server->quic_tp_peer_fn( handshake, ch.quic_tp.buf, ch.quic_tp.bufsz );
487 6084 : }
488 :
489 : /* Reject connection if ALPN not advertised */
490 :
491 6087 : if( server->alpn[0] ) {
492 6084 : if( FD_UNLIKELY( !ch.alpn.bufsz ) )
493 3 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_NO_APPLICATION_PROTOCOL, FD_TLS_REASON_NO_ALPN );
494 6081 : int ok = fd_tls_has_alpn( ch.alpn.buf, ch.alpn.bufsz, server->alpn, server->alpn_sz );
495 6081 : if( FD_UNLIKELY( ok==-1 ) )
496 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_DECODE_ERROR, FD_TLS_REASON_ALPN_PARSE );
497 6081 : if( FD_UNLIKELY( ok==0 ) )
498 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_NO_APPLICATION_PROTOCOL, FD_TLS_REASON_ALPN_NEG );
499 6081 : }
500 :
501 : /* Record client hello in transcript hash */
502 :
503 6084 : fd_sha256_append( &transcript, record, read_sz );
504 :
505 : /* Retry if key share is missing */
506 :
507 6084 : if( !ch.key_share.has_x25519 ) {
508 3 : uchar ch1_hash[ 32 ];
509 3 : fd_sha256_fini( &transcript, ch1_hash );
510 3 : long rc = fd_tls_server_hs_retry( server, handshake, &ch, ch1_hash );
511 3 : /**/ rc = fd_long_if( rc>=0, (long)read_sz, rc );
512 3 : return rc;
513 3 : }
514 :
515 : /* Respond with server hello ****************************************/
516 :
517 : /* Create server random */
518 :
519 6081 : uchar server_random[ 32 ];
520 6081 : if( FD_UNLIKELY( !fd_tls_rand( &server->rand, server_random, 32UL ) ) )
521 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_HANDSHAKE_FAILURE, FD_TLS_REASON_RAND_FAIL );
522 :
523 : /* Create server hello message */
524 :
525 6081 : ulong server_hello_sz;
526 :
527 6081 : do {
528 6081 : uchar * wire = msg_buf;
529 6081 : uchar * const wire_end = msg_buf + MSG_BUFSZ;
530 :
531 : /* Leave space for message header */
532 :
533 6081 : void * hdr_ptr = wire;
534 6081 : wire += sizeof(fd_tls_msg_hdr_t);
535 6081 : fd_tls_msg_hdr_t hdr = { .type = FD_TLS_MSG_SERVER_HELLO };
536 :
537 : /* Construct server hello */
538 :
539 6081 : fd_tls_server_hello_t sh = {
540 6081 : .cipher_suite = FD_TLS_CIPHER_SUITE_AES_128_GCM_SHA256,
541 6081 : .key_share = { .has_x25519 = 1 },
542 6081 : .session_id = ch.session_id,
543 6081 : };
544 6081 : memcpy( sh.random, server_random, 32UL );
545 6081 : memcpy( sh.key_share.x25519, server->kex_public_key, 32UL );
546 :
547 : /* Encode server hello */
548 :
549 6081 : long encode_res = fd_tls_encode_server_hello( &sh, wire, (ulong)(wire_end-wire) );
550 6081 : if( FD_UNLIKELY( encode_res<0L ) )
551 0 : return fd_tls_alert( &handshake->base, (uint)(-encode_res), FD_TLS_REASON_SH_ENCODE );
552 6081 : wire += (ulong)encode_res;
553 :
554 6081 : hdr.sz = fd_uint_to_tls_u24( (uint)encode_res );
555 6081 : fd_tls_encode_msg_hdr( &hdr, hdr_ptr, sizeof(fd_tls_msg_hdr_t) );
556 6081 : server_hello_sz = (ulong)(wire - msg_buf);
557 6081 : } while(0);
558 :
559 : /* Call back with server hello */
560 :
561 6081 : if( FD_UNLIKELY( !server->sendmsg_fn(
562 6081 : handshake,
563 6081 : msg_buf, server_hello_sz,
564 6081 : FD_TLS_LEVEL_INITIAL,
565 6081 : /* flush */ 1 ) ) )
566 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_SENDMSG_FAIL );
567 :
568 : /* Record server hello in transcript hash */
569 :
570 6081 : fd_sha256_append( &transcript, msg_buf, server_hello_sz );
571 :
572 : /* Derive handshake secrets *****************************************/
573 :
574 : /* Export handshake transcript hash */
575 :
576 6081 : fd_sha256_t transcript_clone = transcript;
577 6081 : uchar transcript_hash[ 32 ];
578 6081 : fd_sha256_fini( &transcript_clone, transcript_hash );
579 :
580 : /* Derive ECDH input key material */
581 :
582 6081 : uchar _ecdh_ikm[ 32 ];
583 6081 : void * ecdh_ikm = fd_x25519_exchange( _ecdh_ikm,
584 6081 : server->kex_private_key,
585 6081 : ch.key_share.x25519 );
586 6081 : if( FD_UNLIKELY( !ecdh_ikm ) )
587 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_HANDSHAKE_FAILURE, FD_TLS_REASON_X25519_FAIL );
588 :
589 : /* Derive main handshake secret */
590 :
591 6081 : uchar handshake_secret[ 32 ];
592 6081 : fd_hmac_sha256( /* data */ ecdh_ikm, 32UL,
593 6081 : /* salt */ handshake_derived, 32UL,
594 6081 : /* out */ handshake_secret );
595 :
596 : /* Derive client/server handshake secrets */
597 :
598 6081 : uchar client_hs_secret[ 32UL ];
599 6081 : fd_tls_hkdf_expand_label( client_hs_secret, 32UL,
600 6081 : handshake_secret,
601 6081 : "c hs traffic", 12UL,
602 6081 : transcript_hash, 32UL );
603 6081 : memcpy( handshake->client_hs_secret, client_hs_secret, 32UL );
604 :
605 6081 : uchar server_hs_secret[ 32UL ];
606 6081 : fd_tls_hkdf_expand_label( server_hs_secret, 32UL,
607 6081 : handshake_secret,
608 6081 : "s hs traffic", 12UL,
609 6081 : transcript_hash, 32UL );
610 :
611 : /* Call back with handshake secrets */
612 :
613 6081 : server->secrets_fn( handshake,
614 6081 : /* read secret */ client_hs_secret,
615 6081 : /* write secret */ server_hs_secret,
616 6081 : FD_TLS_LEVEL_HANDSHAKE );
617 :
618 : /* Derive master secret */
619 :
620 6081 : uchar master_derive[ 32 ];
621 6081 : fd_tls_hkdf_expand_label( master_derive, 32UL,
622 6081 : handshake_secret,
623 6081 : "derived", 7UL,
624 6081 : empty_hash, 32UL );
625 :
626 6081 : static uchar const zeros[ 32 ] = {0};
627 6081 : uchar master_secret[ 32 ];
628 6081 : fd_hmac_sha256( /* data */ zeros, 32UL,
629 6081 : /* salt */ master_derive, 32UL,
630 6081 : /* out */ master_secret );
631 :
632 : /* Send EncryptedExtensions (EE) message ****************************/
633 :
634 6081 : ulong server_ee_sz;
635 :
636 6081 : do {
637 6081 : uchar * wire = msg_buf;
638 6081 : uchar * const wire_end = msg_buf + MSG_BUFSZ;
639 :
640 : /* Leave space for message header */
641 :
642 6081 : void * hdr_ptr = wire;
643 6081 : wire += sizeof(fd_tls_msg_hdr_t);
644 6081 : fd_tls_msg_hdr_t hdr = { .type = FD_TLS_MSG_ENCRYPTED_EXT };
645 :
646 6081 : ushort * ext_sz_ptr = (ushort *)wire;
647 6081 : wire += sizeof(ushort);
648 :
649 : /* Construct encrypted extensions */
650 :
651 6081 : fd_tls_enc_ext_t ee = {
652 6081 : .quic_tp = {
653 6081 : .buf = (quic_tp_sz>=0L) ? quic_tp : NULL,
654 6081 : .bufsz = (ushort)quic_tp_sz,
655 6081 : },
656 6081 : .alpn = {
657 6081 : .buf = server->alpn,
658 6081 : .bufsz = server->alpn_sz,
659 6081 : }
660 6081 : };
661 :
662 : /* Negotiate raw public keys if available */
663 :
664 6081 : if( ch.server_cert_types.raw_pubkey ) {
665 0 : handshake->server_cert_rpk = 1;
666 0 : ee.server_cert.cert_type = FD_TLS_CERTTYPE_RAW_PUBKEY;
667 6081 : } else if( !server->cert_x509_sz ) {
668 : /* If server lacks an X.509 certificate and client does not support
669 : raw public keys, abort early. */
670 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_UNSUPPORTED_CERTIFICATE, FD_TLS_REASON_NO_X509 );
671 0 : }
672 :
673 6081 : if( ch.client_cert_types.raw_pubkey ) {
674 0 : handshake->client_cert_rpk = 1;
675 0 : ee.client_cert.cert_type = FD_TLS_CERTTYPE_RAW_PUBKEY;
676 0 : }
677 :
678 : /* Encode encrypted extensions */
679 :
680 6081 : long encode_res = fd_tls_encode_enc_ext( &ee, wire, (ulong)(wire_end-wire) );
681 6081 : if( FD_UNLIKELY( encode_res<0L ) )
682 0 : return fd_tls_alert( &handshake->base, (uint)(-encode_res), FD_TLS_REASON_EE_ENCODE );
683 6081 : wire += (ulong)encode_res;
684 :
685 6081 : *ext_sz_ptr = (ushort)fd_ushort_bswap( (ushort)encode_res );
686 6081 : hdr.sz = fd_uint_to_tls_u24( (uint)encode_res + (uint)sizeof(ushort) );
687 6081 : fd_tls_encode_msg_hdr( &hdr, hdr_ptr, 4UL );
688 6081 : server_ee_sz = (ulong)(wire - msg_buf);
689 6081 : } while(0);
690 :
691 : /* Call back with EE */
692 :
693 6081 : if( FD_UNLIKELY( !server->sendmsg_fn(
694 6081 : handshake,
695 6081 : msg_buf, server_ee_sz,
696 6081 : FD_TLS_LEVEL_HANDSHAKE,
697 6081 : /* flush */ 0 ) ) )
698 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_SENDMSG_FAIL );
699 :
700 : /* Record EE in transcript hash */
701 :
702 6081 : fd_sha256_append( &transcript, msg_buf, server_ee_sz );
703 :
704 : /* Send CertificateRequest ******************************************/
705 :
706 6081 : static uchar const cert_req[] = {
707 6081 : FD_TLS_MSG_CERT_REQ, /* msg_type */
708 6081 : 0x00, 0x00, 0x0b, /* msg_sz */
709 6081 : 0x00, /* certificate_request_context */
710 6081 : 0x00, 0x08, /* extensions length prefix */
711 6081 : 0x00, FD_TLS_EXT_SIGNATURE_ALGORITHMS,
712 : /* ext type */
713 6081 : 0x00, 0x04, /* ext sz */
714 6081 : 0x00, 0x02, /* sigalg sz */
715 6081 : 0x08, 0x07, /* Ed25519 */
716 6081 : };
717 :
718 6081 : if( FD_UNLIKELY( !server->sendmsg_fn(
719 6081 : handshake,
720 6081 : cert_req, sizeof(cert_req),
721 6081 : FD_TLS_LEVEL_HANDSHAKE,
722 6081 : /* flush */ 0 ) ) )
723 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_SENDMSG_FAIL );
724 :
725 : /* Record CertificateRequest in transcript hash */
726 :
727 6081 : fd_sha256_append( &transcript, cert_req, sizeof(cert_req) );
728 :
729 : /* Send Certificate *************************************************/
730 :
731 6081 : ulong cert_msg_sz;
732 6081 : if( ch.server_cert_types.raw_pubkey ) {
733 0 : long sz = fd_tls_encode_raw_public_key( server->cert_public_key, msg_buf, MSG_BUFSZ );
734 0 : FD_TEST( sz>=0L );
735 0 : cert_msg_sz = (ulong)sz;
736 6081 : } else {
737 6081 : long sz = fd_tls_encode_cert_x509( server->cert_x509, server->cert_x509_sz, msg_buf, MSG_BUFSZ );
738 6081 : FD_TEST( sz>=0L );
739 6081 : cert_msg_sz = (ulong)sz;
740 6081 : }
741 :
742 : /* Send certificate message */
743 :
744 6081 : if( FD_UNLIKELY( !server->sendmsg_fn(
745 6081 : handshake,
746 6081 : msg_buf, cert_msg_sz,
747 6081 : FD_TLS_LEVEL_HANDSHAKE,
748 6081 : /* flush */ 0 ) ) )
749 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_SENDMSG_FAIL );
750 :
751 : /* Record Certificate message in transcript hash */
752 :
753 6081 : fd_sha256_append( &transcript, msg_buf, cert_msg_sz );
754 :
755 : /* Send CertificateVerify *******************************************/
756 :
757 6081 : long cvfy_res = fd_tls_send_cert_verify( server, &handshake->base, &transcript, 0 );
758 6081 : if( FD_UNLIKELY( !!cvfy_res ) ) return cvfy_res;
759 : /* CertificateVerify already included in transcript hash */
760 :
761 : /* Send Finished ****************************************************/
762 :
763 : /* Create static size message layout */
764 :
765 6081 : struct __attribute__((packed)) {
766 6081 : fd_tls_msg_hdr_t hdr;
767 6081 : fd_tls_finished_t fin;
768 6081 : } fin_rec;
769 6081 : fin_rec.hdr = (fd_tls_msg_hdr_t){
770 6081 : .type = FD_TLS_MSG_FINISHED,
771 6081 : .sz = fd_uint_to_tls_u24( 0x20 )
772 6081 : };
773 6081 : fd_tls_msg_hdr_bswap( &fin_rec.hdr );
774 6081 : fd_tls_finished_bswap( &fin_rec.fin );
775 :
776 : /* Export transcript hash ClientHello..CertificateVerify */
777 :
778 6081 : transcript_clone = transcript;
779 6081 : fd_sha256_fini( &transcript_clone, transcript_hash );
780 :
781 : /* Derive "Finished" key */
782 :
783 6081 : uchar finished_key[ 32 ];
784 6081 : fd_tls_hkdf_expand_label( finished_key, 32UL,
785 6081 : server_hs_secret,
786 6081 : "finished", 8UL,
787 6081 : NULL, 0UL );
788 :
789 : /* Derive "Finished" verify data */
790 :
791 6081 : fd_hmac_sha256( /* data */ transcript_hash, 32UL,
792 6081 : /* salt */ finished_key, 32UL,
793 6081 : /* out */ fin_rec.fin.verify );
794 :
795 : /* Send Finished message */
796 :
797 6081 : if( FD_UNLIKELY( !server->sendmsg_fn(
798 6081 : handshake,
799 6081 : &fin_rec, sizeof(fin_rec),
800 6081 : FD_TLS_LEVEL_HANDSHAKE,
801 6081 : /* flush */ 1 ) ) )
802 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_SENDMSG_FAIL );
803 :
804 : /* Record Finished in transcript hash */
805 :
806 6081 : fd_sha256_append( &transcript, &fin_rec, sizeof(fin_rec) );
807 :
808 : /* Derive application secrets ***************************************/
809 :
810 : /* Export transcript hash ClientHello..ServerFinished */
811 :
812 6081 : transcript_clone = transcript;
813 6081 : fd_sha256_fini( &transcript_clone, transcript_hash );
814 :
815 : /* Derive client/server application secrets */
816 :
817 6081 : uchar client_app_secret[ 32UL ];
818 6081 : fd_tls_hkdf_expand_label( client_app_secret, 32UL,
819 6081 : master_secret,
820 6081 : "c ap traffic", 12UL,
821 6081 : transcript_hash, 32UL );
822 :
823 6081 : uchar server_app_secret[ 32UL ];
824 6081 : fd_tls_hkdf_expand_label( server_app_secret, 32UL,
825 6081 : master_secret,
826 6081 : "s ap traffic", 12UL,
827 6081 : transcript_hash, 32UL );
828 :
829 : /* Call back with application secrets */
830 :
831 6081 : server->secrets_fn( handshake,
832 6081 : /* read secret */ client_app_secret,
833 6081 : /* write secret */ server_app_secret,
834 6081 : FD_TLS_LEVEL_APPLICATION );
835 :
836 : /* Finish up ********************************************************/
837 :
838 : /* Store transcript hash state */
839 :
840 6081 : fd_tls_transcript_store( &handshake->transcript, &transcript );
841 :
842 : /* Done */
843 :
844 6081 : handshake->base.state = FD_TLS_HS_WAIT_CERT;
845 :
846 6081 : # undef MSG_BUFSZ
847 6081 : return (long)read_sz;
848 6081 : }
849 :
850 : static long
851 : fd_tls_handle_cert_chain( fd_tls_estate_base_t * const base,
852 : uchar const * const cert_chain,
853 : ulong const cert_chain_sz,
854 : uchar const * const expected_pubkey,
855 : uchar * const out_pubkey,
856 12168 : int const is_rpk ) {
857 :
858 12168 : fd_tls_extract_cert_pubkey_res_t extract =
859 12168 : fd_tls_extract_cert_pubkey( cert_chain, cert_chain_sz, fd_uint_if( is_rpk, FD_TLS_CERTTYPE_RAW_PUBKEY, FD_TLS_CERTTYPE_X509 ) );
860 :
861 12168 : if( FD_UNLIKELY( !extract.pubkey ) ) {
862 6 : uint alert = extract.alert ? extract.alert : FD_TLS_ALERT_DECODE_ERROR;
863 6 : ushort reason = extract.reason ? extract.reason : FD_TLS_REASON_CERT_PARSE;
864 6 : return fd_tls_alert( base, alert, reason );
865 6 : }
866 :
867 12162 : if( expected_pubkey )
868 0 : if( FD_UNLIKELY( 0!=memcmp( extract.pubkey, expected_pubkey, 32UL ) ) )
869 0 : return fd_tls_alert( base, FD_TLS_ALERT_HANDSHAKE_FAILURE, FD_TLS_REASON_WRONG_PUBKEY );
870 12162 : if( out_pubkey )
871 12162 : fd_memcpy( out_pubkey, extract.pubkey, 32UL );
872 :
873 : /* Skip extensions */
874 : /* Skip remaining certificate chain */
875 :
876 12162 : return (long)cert_chain_sz;
877 12162 : }
878 :
879 : static long
880 : fd_tls_handle_cert_verify( fd_tls_estate_base_t * hs,
881 : fd_sha256_t const * transcript,
882 : uchar const * record,
883 : ulong record_sz,
884 : uchar const pubkey[ static 32 ],
885 12162 : int is_client ) {
886 :
887 : /* Read CertificateVerify *******************************************/
888 :
889 12162 : fd_tls_cert_verify_t vfy[1] = {{0}};
890 :
891 12162 : ulong read_sz;
892 12162 : do {
893 12162 : uchar const * wire = record;
894 12162 : uchar const * const wire_end = record + record_sz;
895 :
896 : /* Decode message header */
897 :
898 12162 : fd_tls_msg_hdr_t msg_hdr = {0};
899 12162 : long decode_res = fd_tls_decode_msg_hdr( &msg_hdr, wire, (ulong)(wire_end-wire) );
900 12162 : if( FD_UNLIKELY( ( decode_res<0L ) |
901 12162 : ( fd_tls_u24_to_uint( msg_hdr.sz ) != 0x44UL ) ) )
902 0 : return fd_tls_alert( hs, FD_TLS_ALERT_DECODE_ERROR, FD_TLS_REASON_CV_PARSE );
903 12162 : wire += (ulong)decode_res;
904 :
905 12162 : if( FD_UNLIKELY( msg_hdr.type != FD_TLS_MSG_CERT_VERIFY ) )
906 0 : return fd_tls_alert( hs, FD_TLS_ALERT_UNEXPECTED_MESSAGE, FD_TLS_REASON_CV_EXPECTED );
907 :
908 : /* Decode CertificateVerify */
909 :
910 12162 : decode_res = fd_tls_decode_cert_verify( vfy, wire, (ulong)(wire_end-wire) );
911 12162 : if( FD_UNLIKELY( decode_res<0L ) )
912 0 : return fd_tls_alert( hs, (uint)(-decode_res), FD_TLS_REASON_CV_PARSE );
913 12162 : wire += (ulong)decode_res;
914 :
915 12162 : read_sz = (ulong)(wire - record);
916 12162 : } while(0);
917 :
918 12162 : if( FD_UNLIKELY( vfy->sig_alg != FD_TLS_SIGNATURE_ED25519 ) )
919 0 : return fd_tls_alert( hs, FD_TLS_ALERT_HANDSHAKE_FAILURE, FD_TLS_REASON_CV_SIGALG );
920 :
921 : /* Verify signature *************************************************/
922 :
923 : /* Export transcript hash ClientHello..server Certificate
924 : And recover message that was signed */
925 :
926 12162 : uchar sign_msg[ 130 ];
927 12162 : fd_memcpy( sign_msg,
928 12162 : is_client ? fd_tls13_cli_sign_prefix : fd_tls13_srv_sign_prefix,
929 12162 : 98UL );
930 :
931 12162 : fd_sha256_t transcript_clone = *transcript;
932 12162 : fd_sha256_fini( &transcript_clone, sign_msg+98 );
933 :
934 : /* Verify certificate signature
935 : > If the verification fails, the receiver MUST terminate the handshake
936 : > with a "decrypt_error" alert. */
937 :
938 12162 : fd_sha512_t sha512[1];
939 12162 : int sig_err = fd_ed25519_verify( sign_msg, 130UL, vfy->sig, pubkey, sha512 );
940 12162 : if( FD_UNLIKELY( sig_err != FD_ED25519_SUCCESS ) )
941 0 : return fd_tls_alert( hs, FD_TLS_ALERT_DECRYPT_ERROR, FD_TLS_REASON_ED25519_FAIL );
942 :
943 12162 : return (long)read_sz;
944 12162 : }
945 :
946 : static long
947 : fd_tls_server_hs_wait_cert( fd_tls_t const * server,
948 : fd_tls_estate_srv_t * handshake,
949 : uchar const * const record,
950 : ulong const record_sz,
951 6081 : uint encryption_level ) {
952 :
953 6081 : (void)server;
954 :
955 6081 : if( FD_UNLIKELY( encryption_level != FD_TLS_LEVEL_HANDSHAKE ) )
956 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_WRONG_ENC_LVL );
957 :
958 : /* Read Certificate *************************************************/
959 :
960 6081 : ulong read_sz;
961 6081 : do {
962 6081 : uchar const * wire = record;
963 6081 : uchar const * const wire_end = record + record_sz;
964 :
965 : /* Decode message header */
966 :
967 6081 : fd_tls_msg_hdr_t msg_hdr = {0};
968 6081 : long decode_res = fd_tls_decode_msg_hdr( &msg_hdr, wire, (ulong)(wire_end-wire) );
969 6081 : if( FD_UNLIKELY( decode_res<0L ) )
970 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_DECODE_ERROR, FD_TLS_REASON_CERT_PARSE );
971 6081 : wire += (ulong)decode_res;
972 :
973 6081 : if( FD_UNLIKELY( msg_hdr.type != FD_TLS_MSG_CERT ) )
974 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_UNEXPECTED_MESSAGE, FD_TLS_REASON_CERT_EXPECTED );
975 :
976 6081 : ulong msg_sz = fd_tls_u24_to_uint( msg_hdr.sz );
977 6081 : if( FD_UNLIKELY( msg_sz > (ulong)(wire_end-wire) ) )
978 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_DECODE_ERROR, FD_TLS_REASON_CERT_CR_PARSE );
979 :
980 : /* Decode Certificate */
981 :
982 6081 : decode_res = fd_tls_handle_cert_chain( &handshake->base, wire, msg_sz, NULL, handshake->client_pubkey, handshake->client_cert_rpk );
983 6081 : if( FD_UNLIKELY( decode_res<0L ) )
984 0 : return fd_tls_alert( &handshake->base, (uint)(-decode_res), FD_TLS_REASON_CERT_PARSE );
985 6081 : wire += (ulong)decode_res;
986 :
987 6081 : read_sz = (ulong)(wire - record);
988 6081 : } while(0);
989 :
990 6081 : fd_sha256_t transcript;
991 6081 : fd_tls_transcript_load( &handshake->transcript, &transcript );
992 6081 : fd_sha256_append( &transcript, record, read_sz );
993 6081 : fd_tls_transcript_store( &handshake->transcript, &transcript );
994 :
995 : /* Finish up ********************************************************/
996 :
997 6081 : handshake->base.state = FD_TLS_HS_WAIT_CV;
998 6081 : return (long)read_sz;
999 6081 : }
1000 :
1001 : static long
1002 : fd_tls_server_hs_wait_cert_verify( fd_tls_t const * server,
1003 : fd_tls_estate_srv_t * hs,
1004 : uchar const * const record,
1005 : ulong const record_sz,
1006 6081 : uint encryption_level ) {
1007 :
1008 6081 : (void)server;
1009 :
1010 6081 : if( FD_UNLIKELY( encryption_level != FD_TLS_LEVEL_HANDSHAKE ) )
1011 0 : return fd_tls_alert( &hs->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_WRONG_ENC_LVL );
1012 :
1013 6081 : fd_sha256_t transcript;
1014 6081 : fd_tls_transcript_load( &hs->transcript, &transcript );
1015 6081 : fd_sha256_t transcript_clone = transcript;
1016 :
1017 : /* Decode incoming client CertificateVerify *************************/
1018 :
1019 6081 : long res = fd_tls_handle_cert_verify( &hs->base, &transcript_clone, record, record_sz, hs->client_pubkey, 1 );
1020 6081 : if( FD_UNLIKELY( res<0L ) ) return res;
1021 :
1022 6081 : fd_sha256_append( &transcript, record, (ulong)res );
1023 6081 : fd_tls_transcript_store( &hs->transcript, &transcript );
1024 :
1025 : /* Finish up ********************************************************/
1026 :
1027 6081 : hs->base.state = FD_TLS_HS_WAIT_FINISHED;
1028 6081 : return res;
1029 6081 : }
1030 :
1031 : static long
1032 : fd_tls_server_hs_wait_finished( fd_tls_t const * server,
1033 : fd_tls_estate_srv_t * handshake,
1034 : uchar const * const record,
1035 : ulong record_sz,
1036 6081 : uint encryption_level ) {
1037 :
1038 6081 : (void)server;
1039 :
1040 6081 : if( FD_UNLIKELY( encryption_level != FD_TLS_LEVEL_HANDSHAKE ) )
1041 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_WRONG_ENC_LVL );
1042 :
1043 : /* Restore state ****************************************************/
1044 :
1045 6081 : fd_sha256_t transcript;
1046 6081 : fd_tls_transcript_load( &handshake->transcript, &transcript );
1047 :
1048 : /* Decode incoming client "Finished" message ************************/
1049 :
1050 6081 : fd_tls_finished_t finished = {0};
1051 :
1052 6081 : ulong read_sz;
1053 6081 : do {
1054 6081 : uchar const * wire = record;
1055 6081 : uchar const * const wire_end = record + record_sz;
1056 :
1057 : /* Decode message header */
1058 :
1059 6081 : fd_tls_msg_hdr_t msg_hdr = {0};
1060 6081 : long decode_res = fd_tls_decode_msg_hdr( &msg_hdr, wire, (ulong)(wire_end-wire) );
1061 6081 : if( FD_UNLIKELY( decode_res<0L ) )
1062 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_DECODE_ERROR, FD_TLS_REASON_FINI_PARSE );
1063 6081 : wire += (ulong)decode_res;
1064 :
1065 6081 : if( FD_UNLIKELY( msg_hdr.type != FD_TLS_MSG_FINISHED ) )
1066 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_UNEXPECTED_MESSAGE, FD_TLS_REASON_FINI_EXPECTED );
1067 :
1068 : /* Decode server Finished */
1069 :
1070 6081 : decode_res = fd_tls_decode_finished( &finished, wire, (ulong)(wire_end-wire) );
1071 6081 : if( FD_UNLIKELY( decode_res<0L ) )
1072 0 : return fd_tls_alert( &handshake->base, (uint)(-decode_res), FD_TLS_REASON_FINI_PARSE );
1073 6081 : wire += (ulong)decode_res;
1074 :
1075 6081 : read_sz = (ulong)(wire - record);
1076 6081 : } while(0);
1077 :
1078 : /* Check "Finished" verify data *************************************/
1079 :
1080 : /* Export transcript hash */
1081 :
1082 6081 : uchar transcript_hash[ 32 ];
1083 6081 : fd_sha256_fini( &transcript, transcript_hash );
1084 :
1085 : /* Derive "Finished" key */
1086 :
1087 6081 : uchar finished_key[ 32 ];
1088 6081 : fd_tls_hkdf_expand_label( finished_key, 32UL,
1089 6081 : handshake->client_hs_secret,
1090 6081 : "finished", 8UL,
1091 6081 : NULL, 0UL );
1092 :
1093 : /* Derive "Finished" verify data */
1094 :
1095 6081 : uchar finished_expected[ 32 ];
1096 6081 : fd_hmac_sha256( /* data */ transcript_hash, 32UL,
1097 6081 : /* salt */ finished_key, 32UL,
1098 6081 : /* out */ finished_expected );
1099 :
1100 : /* Verify that client and server's transcripts match */
1101 :
1102 6081 : int match = 0;
1103 200673 : for( ulong i=0; i<32UL; i++ )
1104 194592 : match |= finished.verify[i] ^ finished_expected[i];
1105 6081 : if( FD_UNLIKELY( match!=0 ) )
1106 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_DECRYPT_ERROR, FD_TLS_REASON_FINI_FAIL );
1107 :
1108 : /* Done */
1109 :
1110 6081 : handshake->base.state = FD_TLS_HS_CONNECTED;
1111 6081 : return (long)read_sz;
1112 6081 : }
1113 :
1114 : static long fd_tls_client_hs_start ( fd_tls_t const *, fd_tls_estate_cli_t * );
1115 : static long fd_tls_client_hs_wait_sh ( fd_tls_t const *, fd_tls_estate_cli_t *, uchar const *, ulong, uint );
1116 : static long fd_tls_client_hs_wait_ee ( fd_tls_t const *, fd_tls_estate_cli_t *, uchar const *, ulong, uint );
1117 : static long fd_tls_client_hs_wait_cert_cr ( fd_tls_t const *, fd_tls_estate_cli_t *, uchar const *, ulong, uint );
1118 : static long fd_tls_client_hs_wait_cert ( fd_tls_t const *, fd_tls_estate_cli_t *, uchar const *, ulong, uint );
1119 : static long fd_tls_client_hs_wait_cert_verify( fd_tls_t const *, fd_tls_estate_cli_t *, uchar const *, ulong, uint );
1120 : static long fd_tls_client_hs_wait_finished ( fd_tls_t const *, fd_tls_estate_cli_t *, uchar const *, ulong, uint );
1121 :
1122 : long
1123 : fd_tls_client_handshake( fd_tls_t const * client,
1124 : fd_tls_estate_cli_t * handshake,
1125 : void const * record,
1126 : ulong record_sz,
1127 42609 : uint encryption_level ) {
1128 42609 : switch( handshake->base.state ) {
1129 6117 : case FD_TLS_HS_START:
1130 : /* Record argument is ignored, since ClientHello is always the first message */
1131 6117 : (void)record; (void)record_sz; (void)encryption_level;
1132 6117 : return fd_tls_client_hs_start( client, handshake );
1133 6084 : case FD_TLS_HS_WAIT_SH:
1134 : /* Incoming ServerHello */
1135 6084 : return fd_tls_client_hs_wait_sh( client, handshake, record, record_sz, encryption_level );
1136 6081 : case FD_TLS_HS_WAIT_EE:
1137 : /* Incoming EncryptedExtensions */
1138 6081 : return fd_tls_client_hs_wait_ee( client, handshake, record, record_sz, encryption_level );
1139 6087 : case FD_TLS_HS_WAIT_CERT_CR:
1140 : /* Incoming CertificateRequest or Certificate */
1141 6087 : return fd_tls_client_hs_wait_cert_cr( client, handshake, record, record_sz, encryption_level );
1142 6078 : case FD_TLS_HS_WAIT_CERT:
1143 : /* Incoming Certificate */
1144 6078 : return fd_tls_client_hs_wait_cert( client, handshake, record, record_sz, encryption_level );
1145 6081 : case FD_TLS_HS_WAIT_CV:
1146 : /* Incoming CertificateVerify */
1147 6081 : return fd_tls_client_hs_wait_cert_verify( client, handshake, record, record_sz, encryption_level );
1148 6081 : case FD_TLS_HS_WAIT_FINISHED:
1149 : /* Incoming Server Finished */
1150 6081 : return fd_tls_client_hs_wait_finished( client, handshake, record, record_sz, encryption_level );
1151 0 : default:
1152 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_HANDSHAKE_FAILURE, FD_TLS_REASON_ILLEGAL_STATE );
1153 42609 : }
1154 42609 : }
1155 :
1156 : static long
1157 : fd_tls_client_hs_start( fd_tls_t const * const client,
1158 6117 : fd_tls_estate_cli_t * const handshake ) {
1159 :
1160 : /* Request QUIC transport params */
1161 6117 : uchar quic_tp[ FD_TLS_EXT_QUIC_PARAMS_SZ_MAX ];
1162 6117 : long quic_tp_sz = -1L;
1163 6117 : if( client->quic )
1164 6111 : quic_tp_sz = (long)client->quic_tp_self_fn( handshake, quic_tp, FD_TLS_EXT_QUIC_PARAMS_SZ_MAX );
1165 6117 : if( FD_UNLIKELY( quic_tp_sz > (long)FD_TLS_EXT_QUIC_PARAMS_SZ_MAX ) )
1166 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_DECODE_ERROR, FD_TLS_REASON_QUIC_TP_OVERSZ );
1167 :
1168 : /* Message buffer */
1169 6117 : # define MSG_BUFSZ 512UL
1170 6117 : uchar msg_buf[ MSG_BUFSZ ];
1171 :
1172 : /* Transcript hasher */
1173 6117 : fd_sha256_init( &handshake->transcript );
1174 :
1175 : /* Send ClientHello *************************************************/
1176 :
1177 : /* Create client random */
1178 :
1179 6117 : uchar client_random[ 32 ];
1180 6117 : if( FD_UNLIKELY( !fd_tls_rand( &client->rand, client_random, 32UL ) ) )
1181 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_RAND_FAIL );
1182 :
1183 : /* Remember client random for SSLKEYLOGFILE */
1184 6117 : fd_memcpy( handshake->base.client_random, client_random, 32UL );
1185 :
1186 : /* Create client hello message */
1187 :
1188 6117 : ulong client_hello_sz;
1189 :
1190 6117 : do {
1191 6117 : uchar * wire = msg_buf;
1192 6117 : uchar * const wire_end = msg_buf + MSG_BUFSZ;
1193 :
1194 : /* Leave space for message header */
1195 :
1196 6117 : void * hdr_ptr = wire;
1197 6117 : wire += sizeof(fd_tls_msg_hdr_t);
1198 6117 : fd_tls_msg_hdr_t hdr = { .type = FD_TLS_MSG_CLIENT_HELLO };
1199 :
1200 : /* Construct client hello */
1201 :
1202 6117 : fd_tls_client_hello_t ch = {
1203 6117 : .supported_versions = { .tls13=1 },
1204 6117 : .supported_groups = { .x25519=1 },
1205 6117 : .signature_algorithms = { .ed25519=1 },
1206 6117 : .cipher_suites = { .aes_128_gcm_sha256=1 },
1207 6117 : .key_share = { .has_x25519=1 },
1208 6117 : .quic_tp = {
1209 6117 : .buf = (quic_tp_sz>=0L) ? quic_tp : NULL,
1210 6117 : .bufsz = (quic_tp_sz>=0L) ? (ushort)quic_tp_sz : 0,
1211 6117 : },
1212 6117 : .alpn = {
1213 6117 : .buf = client->alpn,
1214 6117 : .bufsz = client->alpn_sz,
1215 6117 : }
1216 6117 : };
1217 6117 : memcpy( ch.random, client_random, 32UL );
1218 6117 : memcpy( ch.key_share.x25519, client->kex_public_key, 32UL );
1219 :
1220 : /* Encode client hello */
1221 :
1222 6117 : long encode_res = fd_tls_encode_client_hello( &ch, wire, (ulong)(wire_end-wire) );
1223 6117 : if( FD_UNLIKELY( encode_res<0L ) )
1224 0 : return fd_tls_alert( &handshake->base, (uint)(-encode_res), FD_TLS_REASON_CH_ENCODE );
1225 6117 : wire += (ulong)encode_res;
1226 :
1227 6117 : hdr.sz = fd_uint_to_tls_u24( (uint)encode_res );
1228 6117 : fd_tls_encode_msg_hdr( &hdr, hdr_ptr, sizeof(fd_tls_msg_hdr_t) );
1229 6117 : client_hello_sz = (ulong)(wire - msg_buf);
1230 6117 : } while(0);
1231 :
1232 : /* Call back with client hello */
1233 :
1234 6117 : if( FD_UNLIKELY( !client->sendmsg_fn(
1235 6117 : handshake,
1236 6117 : msg_buf, client_hello_sz,
1237 6117 : FD_TLS_LEVEL_INITIAL,
1238 6117 : /* flush */ 1 ) ) )
1239 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_SENDMSG_FAIL );
1240 :
1241 : /* Record client hello in transcript hash */
1242 :
1243 6117 : fd_sha256_append( &handshake->transcript, msg_buf, client_hello_sz );
1244 :
1245 : /* Finish up ********************************************************/
1246 :
1247 6117 : handshake->base.state = FD_TLS_HS_WAIT_SH;
1248 :
1249 6117 : # undef MSG_BUFSZ
1250 6117 : return 0L;
1251 6117 : }
1252 :
1253 : static long
1254 : fd_tls_client_hs_wait_sh( fd_tls_t const * const client,
1255 : fd_tls_estate_cli_t * const handshake,
1256 : uchar const * const record,
1257 : ulong const record_sz,
1258 6084 : uint const encryption_level ) {
1259 :
1260 6084 : if( FD_UNLIKELY( encryption_level != FD_TLS_LEVEL_INITIAL ) )
1261 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_WRONG_ENC_LVL );
1262 :
1263 : /* Read server hello ************************************************/
1264 :
1265 6084 : fd_tls_server_hello_t sh[1] = {0};
1266 :
1267 6084 : ulong read_sz;
1268 6084 : do {
1269 6084 : uchar const * wire = record;
1270 6084 : uchar const * const wire_end = record + record_sz;
1271 :
1272 : /* Decode message header */
1273 :
1274 6084 : fd_tls_msg_hdr_t msg_hdr = {0};
1275 6084 : long decode_res = fd_tls_decode_msg_hdr( &msg_hdr, wire, (ulong)(wire_end-wire) );
1276 6084 : if( FD_UNLIKELY( decode_res<0L ) )
1277 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_DECODE_ERROR, FD_TLS_REASON_SH_PARSE );
1278 6084 : wire += (ulong)decode_res;
1279 :
1280 6084 : if( FD_UNLIKELY( msg_hdr.type != FD_TLS_MSG_SERVER_HELLO ) )
1281 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_UNEXPECTED_MESSAGE, FD_TLS_REASON_SH_EXPECTED );
1282 :
1283 : /* Decode Server Hello */
1284 :
1285 6084 : decode_res = fd_tls_decode_server_hello( sh, wire, (ulong)(wire_end-wire) );
1286 6084 : if( FD_UNLIKELY( decode_res<0L ) )
1287 3 : return fd_tls_alert( &handshake->base, (uint)(-decode_res), FD_TLS_REASON_SH_PARSE );
1288 6081 : wire += (ulong)decode_res;
1289 :
1290 6081 : read_sz = (ulong)(wire - record);
1291 6081 : } while(0);
1292 :
1293 : /* Record server hello in transcript hash */
1294 :
1295 6081 : fd_sha256_append( &handshake->transcript, record, read_sz );
1296 :
1297 : /* TODO: For now, cryptographic parameters are hardcoded in the
1298 : decoder. Thus, we skip checks. */
1299 :
1300 : /* Derive handshake secrets *****************************************/
1301 :
1302 : /* TODO: This code is duplicated server-side */
1303 :
1304 : /* Export handshake transcript hash */
1305 :
1306 6081 : fd_sha256_t transcript_clone = handshake->transcript;
1307 6081 : uchar transcript_hash[ 32 ];
1308 6081 : fd_sha256_fini( &transcript_clone, transcript_hash );
1309 :
1310 : /* Derive ECDH input key material */
1311 :
1312 6081 : uchar _ecdh_ikm[ 32 ];
1313 6081 : void * ecdh_ikm = fd_x25519_exchange( _ecdh_ikm,
1314 6081 : client->kex_private_key,
1315 6081 : sh->key_share.x25519 );
1316 6081 : if( FD_UNLIKELY( !ecdh_ikm ) )
1317 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_HANDSHAKE_FAILURE, FD_TLS_REASON_X25519_FAIL );
1318 :
1319 : /* Derive main handshake secret */
1320 :
1321 6081 : uchar handshake_secret[ 32 ];
1322 6081 : fd_hmac_sha256( /* data */ ecdh_ikm, 32UL,
1323 6081 : /* salt */ handshake_derived, 32UL,
1324 6081 : /* out */ handshake_secret );
1325 :
1326 : /* Derive client/server handshake secrets */
1327 :
1328 6081 : fd_tls_hkdf_expand_label( handshake->client_hs_secret, 32UL,
1329 6081 : handshake_secret,
1330 6081 : "c hs traffic", 12UL,
1331 6081 : transcript_hash, 32UL );
1332 :
1333 6081 : fd_tls_hkdf_expand_label( handshake->server_hs_secret, 32UL,
1334 6081 : handshake_secret,
1335 6081 : "s hs traffic", 12UL,
1336 6081 : transcript_hash, 32UL );
1337 :
1338 : /* Call back with handshake secrets */
1339 :
1340 6081 : client->secrets_fn( handshake,
1341 6081 : /* read secret */ handshake->server_hs_secret,
1342 6081 : /* write secret */ handshake->client_hs_secret,
1343 6081 : FD_TLS_LEVEL_HANDSHAKE );
1344 :
1345 : /* Derive master secret */
1346 :
1347 6081 : uchar master_derive[ 32 ];
1348 6081 : fd_tls_hkdf_expand_label( master_derive, 32UL,
1349 6081 : handshake_secret,
1350 6081 : "derived", 7UL,
1351 6081 : empty_hash, 32UL );
1352 :
1353 6081 : static uchar const zeros[ 32 ] = {0};
1354 6081 : fd_hmac_sha256( /* data */ zeros, 32UL,
1355 6081 : /* salt */ master_derive, 32UL,
1356 6081 : /* out */ handshake->master_secret );
1357 :
1358 : /* Finish up ********************************************************/
1359 :
1360 6081 : handshake->base.state = FD_TLS_HS_WAIT_EE;
1361 :
1362 6081 : return (long)read_sz;
1363 6081 : }
1364 :
1365 : static long
1366 : fd_tls_client_hs_wait_ee( fd_tls_t const * const client,
1367 : fd_tls_estate_cli_t * const handshake,
1368 : uchar const * const record,
1369 : ulong const record_sz,
1370 6081 : uint const encryption_level ) {
1371 :
1372 6081 : if( FD_UNLIKELY( encryption_level != FD_TLS_LEVEL_HANDSHAKE ) )
1373 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_WRONG_ENC_LVL );
1374 :
1375 : /* Read EncryptedExtensions (EE) message ****************************/
1376 :
1377 6081 : fd_tls_enc_ext_t ee[1] = {0};
1378 :
1379 6081 : ulong read_sz;
1380 6081 : do {
1381 6081 : uchar const * wire = record;
1382 6081 : uchar const * const wire_end = record + record_sz;
1383 :
1384 : /* Decode message header */
1385 :
1386 6081 : fd_tls_msg_hdr_t msg_hdr = {0};
1387 6081 : long decode_res = fd_tls_decode_msg_hdr( &msg_hdr, wire, (ulong)(wire_end-wire) );
1388 6081 : if( FD_UNLIKELY( decode_res<0L ) )
1389 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_DECODE_ERROR, FD_TLS_REASON_EE_PARSE );
1390 6081 : wire += (ulong)decode_res;
1391 :
1392 6081 : if( FD_UNLIKELY( msg_hdr.type != FD_TLS_MSG_ENCRYPTED_EXT ) )
1393 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_UNEXPECTED_MESSAGE, FD_TLS_REASON_EE_EXPECTED );
1394 :
1395 : /* Decode EncryptedExtensions */
1396 :
1397 6081 : decode_res = fd_tls_decode_enc_ext( ee, wire, (ulong)(wire_end-wire) );
1398 6081 : if( FD_UNLIKELY( decode_res<0L ) )
1399 0 : return fd_tls_alert( &handshake->base, (uint)(-decode_res), FD_TLS_REASON_EE_PARSE );
1400 6081 : wire += (ulong)decode_res;
1401 :
1402 6081 : read_sz = (ulong)(wire - record);
1403 6081 : } while(0);
1404 :
1405 : /* Record EE in transcript hash */
1406 :
1407 6081 : fd_sha256_append( &handshake->transcript, record, read_sz );
1408 :
1409 6081 : switch( ee->server_cert.cert_type ) {
1410 6081 : case FD_TLS_CERTTYPE_X509:
1411 6081 : break; /* ok */
1412 0 : case FD_TLS_CERTTYPE_RAW_PUBKEY:
1413 0 : handshake->server_cert_rpk = 1;
1414 0 : break;
1415 0 : default:
1416 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_UNSUPPORTED_CERTIFICATE, FD_TLS_REASON_CERT_TYPE );
1417 6081 : }
1418 :
1419 6081 : handshake->client_cert_nox509 = 1;
1420 6081 : switch( ee->client_cert.cert_type ) {
1421 6081 : case FD_TLS_CERTTYPE_X509:
1422 6081 : handshake->client_cert_nox509 = 0;
1423 6081 : break;
1424 0 : case FD_TLS_CERTTYPE_RAW_PUBKEY:
1425 0 : handshake->client_cert_rpk = 1;
1426 0 : break;
1427 0 : default:
1428 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_UNSUPPORTED_CERTIFICATE, FD_TLS_REASON_CERT_TYPE );
1429 6081 : }
1430 :
1431 : /* QUIC mode */
1432 :
1433 6081 : if( client->quic ) {
1434 : /* QUIC transport parameters are mandatory in QUIC mode */
1435 6078 : if( FD_UNLIKELY( !ee->quic_tp.buf ) )
1436 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_MISSING_EXTENSION, FD_TLS_REASON_EE_NO_QUIC );
1437 :
1438 : /* Inform user of peer's QUIC transport parameters */
1439 6078 : client->quic_tp_peer_fn( handshake, ee->quic_tp.buf, ee->quic_tp.bufsz );
1440 6078 : }
1441 :
1442 : /* Check ALPN */
1443 :
1444 6081 : if( client->alpn_sz ) {
1445 6078 : if( FD_UNLIKELY( !ee->alpn.bufsz ) )
1446 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_MISSING_EXTENSION, FD_TLS_REASON_NO_ALPN );
1447 6078 : if( FD_UNLIKELY( ee->alpn.bufsz != client->alpn_sz ||
1448 6078 : 0!=memcmp( ee->alpn.buf, client->alpn, client->alpn_sz ) ) )
1449 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_HANDSHAKE_FAILURE, FD_TLS_REASON_ALPN_NEG );
1450 6078 : }
1451 :
1452 : /* Fail if server requested an X.509 client cert, but we can only
1453 : serve a raw public key. */
1454 :
1455 6081 : if( FD_UNLIKELY( ( !!handshake->client_cert )
1456 6081 : & ( !handshake->client_cert_rpk )
1457 6081 : & ( ( !client->cert_x509_sz )
1458 6081 : | ( !!handshake->client_cert_nox509 ) ) ) )
1459 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_UNSUPPORTED_CERTIFICATE, FD_TLS_REASON_NO_X509 );
1460 :
1461 : /* Finish up ********************************************************/
1462 :
1463 6081 : handshake->base.state = FD_TLS_HS_WAIT_CERT_CR;
1464 :
1465 6081 : return (long)read_sz;
1466 6081 : }
1467 :
1468 : static long
1469 : fd_tls_client_handle_cert_req( fd_tls_estate_cli_t * const handshake,
1470 : uchar const * const req,
1471 6078 : ulong const req_sz ) {
1472 :
1473 : /* For now, just ignore the content of the certificate request.
1474 : TODO: This is obviously not compliant. */
1475 6078 : (void)req;
1476 :
1477 6078 : handshake->client_cert = 1;
1478 6078 : handshake->base.state = FD_TLS_HS_WAIT_CERT;
1479 :
1480 6078 : return (long)req_sz;
1481 6078 : }
1482 :
1483 : static long
1484 : fd_tls_client_handle_cert_chain( fd_tls_estate_cli_t * const hs,
1485 : uchar const * const cert_chain,
1486 6087 : ulong const cert_chain_sz ) {
1487 : /* pubkey pinning is ...
1488 : ... enabled => check that public key matches cert
1489 : ... disabled => update the handshake's public key value based on cert */
1490 6087 : uchar const * expected_pubkey = ( hs->server_pubkey_pin) ? (hs->server_pubkey) : NULL;
1491 6087 : uchar * out_pubkey = (!hs->server_pubkey_pin) ? (hs->server_pubkey) : NULL;
1492 6087 : return fd_tls_handle_cert_chain( &hs->base, cert_chain, cert_chain_sz, expected_pubkey, out_pubkey, hs->server_cert_rpk );
1493 6087 : }
1494 :
1495 : static long
1496 : fd_tls_client_hs_wait_cert_cr( fd_tls_t const * const client,
1497 : fd_tls_estate_cli_t * const handshake,
1498 : uchar const * const record,
1499 : ulong const record_sz,
1500 6087 : uint const encryption_level ) {
1501 :
1502 6087 : (void)client;
1503 :
1504 6087 : if( FD_UNLIKELY( encryption_level != FD_TLS_LEVEL_HANDSHAKE ) )
1505 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_WRONG_ENC_LVL );
1506 :
1507 : /* Read Certificate(Request) ****************************************/
1508 :
1509 6087 : uchar next_state;
1510 :
1511 6087 : ulong read_sz;
1512 6087 : do {
1513 6087 : uchar const * wire = record;
1514 6087 : uchar const * const wire_end = record + record_sz;
1515 :
1516 : /* Decode message header */
1517 :
1518 6087 : fd_tls_msg_hdr_t msg_hdr = {0};
1519 6087 : long decode_res = fd_tls_decode_msg_hdr( &msg_hdr, wire, (ulong)(wire_end-wire) );
1520 6087 : if( FD_UNLIKELY( decode_res<0L ) )
1521 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_DECODE_ERROR, FD_TLS_REASON_CERT_CR_PARSE );
1522 6087 : wire += (ulong)decode_res;
1523 :
1524 6087 : ulong msg_sz = fd_tls_u24_to_uint( msg_hdr.sz );
1525 6087 : if( FD_UNLIKELY( msg_sz > (ulong)(wire_end-wire) ) )
1526 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_DECODE_ERROR, FD_TLS_REASON_CERT_CR_PARSE );
1527 :
1528 6087 : switch( msg_hdr.type ) {
1529 6078 : case FD_TLS_MSG_CERT_REQ:
1530 6078 : decode_res = fd_tls_client_handle_cert_req ( handshake, wire, msg_sz );
1531 6078 : next_state = FD_TLS_HS_WAIT_CERT;
1532 6078 : break;
1533 9 : case FD_TLS_MSG_CERT:
1534 9 : decode_res = fd_tls_client_handle_cert_chain( handshake, wire, msg_sz );
1535 9 : next_state = FD_TLS_HS_WAIT_CV;
1536 9 : break;
1537 0 : default:
1538 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_UNEXPECTED_MESSAGE, FD_TLS_REASON_CERT_CR_EXPECTED );
1539 6087 : }
1540 :
1541 6087 : if( FD_UNLIKELY( decode_res<0L ) )
1542 6 : return fd_tls_alert( &handshake->base, (uint)(-decode_res), FD_TLS_REASON_CERT_CR_PARSE );
1543 6081 : wire += (ulong)decode_res;
1544 :
1545 6081 : read_sz = (ulong)(wire - record);
1546 6081 : } while(0);
1547 :
1548 6081 : fd_sha256_append( &handshake->transcript, record, read_sz );
1549 :
1550 : /* Finish up ********************************************************/
1551 :
1552 6081 : handshake->base.state = ((uchar)next_state);
1553 6081 : return (long)read_sz;
1554 6087 : }
1555 :
1556 : static long
1557 : fd_tls_client_hs_wait_cert( fd_tls_t const * const client,
1558 : fd_tls_estate_cli_t * const handshake,
1559 : uchar const * const record,
1560 : ulong const record_sz,
1561 6078 : uint const encryption_level ) {
1562 :
1563 6078 : (void)client;
1564 :
1565 6078 : if( FD_UNLIKELY( encryption_level != FD_TLS_LEVEL_HANDSHAKE ) )
1566 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_WRONG_ENC_LVL );
1567 :
1568 : /* Read Certificate *************************************************/
1569 :
1570 6078 : ulong read_sz;
1571 6078 : do {
1572 6078 : uchar const * wire = record;
1573 6078 : uchar const * const wire_end = record + record_sz;
1574 :
1575 : /* Decode message header */
1576 :
1577 6078 : fd_tls_msg_hdr_t msg_hdr = {0};
1578 6078 : long decode_res = fd_tls_decode_msg_hdr( &msg_hdr, wire, (ulong)(wire_end-wire) );
1579 6078 : if( FD_UNLIKELY( decode_res<0L ) )
1580 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_DECODE_ERROR, FD_TLS_REASON_CERT_PARSE );
1581 6078 : wire += (ulong)decode_res;
1582 :
1583 6078 : if( FD_UNLIKELY( msg_hdr.type != FD_TLS_MSG_CERT ) )
1584 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_UNEXPECTED_MESSAGE, FD_TLS_REASON_CERT_EXPECTED );
1585 :
1586 6078 : ulong msg_sz = fd_tls_u24_to_uint( msg_hdr.sz );
1587 6078 : if( FD_UNLIKELY( msg_sz > (ulong)(wire_end-wire) ) )
1588 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_DECODE_ERROR, FD_TLS_REASON_CERT_CR_PARSE );
1589 :
1590 : /* Decode Certificate */
1591 :
1592 6078 : decode_res = fd_tls_client_handle_cert_chain( handshake, wire, msg_sz );
1593 6078 : if( FD_UNLIKELY( decode_res<0L ) )
1594 0 : return fd_tls_alert( &handshake->base, (uint)(-decode_res), FD_TLS_REASON_CERT_PARSE );
1595 6078 : wire += (ulong)decode_res;
1596 :
1597 6078 : read_sz = (ulong)(wire - record);
1598 6078 : } while(0);
1599 :
1600 6078 : fd_sha256_append( &handshake->transcript, record, read_sz );
1601 :
1602 : /* Finish up ********************************************************/
1603 :
1604 6078 : handshake->base.state = (char)FD_TLS_HS_WAIT_CV;
1605 6078 : return (long)read_sz;
1606 6078 : }
1607 :
1608 : static long
1609 : fd_tls_client_hs_wait_cert_verify( fd_tls_t const * const client,
1610 : fd_tls_estate_cli_t * const hs,
1611 : uchar const * const record,
1612 : ulong const record_sz,
1613 6081 : uint const encryption_level ) {
1614 :
1615 6081 : (void)client;
1616 :
1617 6081 : if( FD_UNLIKELY( encryption_level != FD_TLS_LEVEL_HANDSHAKE ) )
1618 0 : return fd_tls_alert( &hs->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_WRONG_ENC_LVL );
1619 :
1620 : /* Decode incoming server CertificateVerify *************************/
1621 :
1622 6081 : long res = fd_tls_handle_cert_verify( &hs->base, &hs->transcript, record, record_sz, hs->server_pubkey, 0 );
1623 6081 : if( FD_UNLIKELY( res<0L ) ) return res;
1624 :
1625 6081 : fd_sha256_append( &hs->transcript, record, (ulong)res );
1626 :
1627 : /* Finish up ********************************************************/
1628 :
1629 6081 : hs->base.state = FD_TLS_HS_WAIT_FINISHED;
1630 6081 : return res;
1631 6081 : }
1632 :
1633 : static long
1634 : fd_tls_client_hs_wait_finished( fd_tls_t const * const client,
1635 : fd_tls_estate_cli_t * const hs,
1636 : uchar const * const record,
1637 : ulong const record_sz,
1638 6081 : uint const encryption_level ) {
1639 :
1640 6081 : if( FD_UNLIKELY( encryption_level != FD_TLS_LEVEL_HANDSHAKE ) )
1641 0 : return fd_tls_alert( &hs->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_WRONG_ENC_LVL );
1642 :
1643 : /* Export transcript hash ClientHello..CertificateVerify */
1644 :
1645 6081 : fd_sha256_t transcript_clone = hs->transcript;
1646 6081 : uchar transcript_hash[ 32 ];
1647 6081 : fd_sha256_fini( &transcript_clone, transcript_hash );
1648 :
1649 : /* Derive "Finished" key */
1650 :
1651 6081 : uchar server_finished_key[ 32 ];
1652 6081 : fd_tls_hkdf_expand_label( server_finished_key, 32UL,
1653 6081 : hs->server_hs_secret,
1654 6081 : "finished", 8UL,
1655 6081 : NULL, 0UL );
1656 :
1657 : /* Derive "Finished" verify data */
1658 :
1659 6081 : uchar server_finished_expected[ 32 ];
1660 6081 : fd_hmac_sha256( /* data */ transcript_hash, 32UL,
1661 6081 : /* salt */ server_finished_key, 32UL,
1662 6081 : /* out */ server_finished_expected );
1663 :
1664 : /* Read ServerFinished **********************************************/
1665 :
1666 6081 : fd_tls_finished_t server_fin = {0};
1667 :
1668 6081 : ulong read_sz;
1669 6081 : do {
1670 6081 : uchar const * wire = record;
1671 6081 : uchar const * const wire_end = record + record_sz;
1672 :
1673 : /* Decode message header */
1674 :
1675 6081 : fd_tls_msg_hdr_t msg_hdr = {0};
1676 6081 : long decode_res = fd_tls_decode_msg_hdr( &msg_hdr, wire, (ulong)(wire_end-wire) );
1677 6081 : if( FD_UNLIKELY( decode_res<0L ) )
1678 0 : return fd_tls_alert( &hs->base, FD_TLS_ALERT_DECODE_ERROR, FD_TLS_REASON_FINI_PARSE );
1679 6081 : wire += (ulong)decode_res;
1680 :
1681 6081 : if( FD_UNLIKELY( msg_hdr.type != FD_TLS_MSG_FINISHED ) )
1682 0 : return fd_tls_alert( &hs->base, FD_TLS_ALERT_UNEXPECTED_MESSAGE, FD_TLS_REASON_FINI_EXPECTED );
1683 :
1684 : /* Decode server Finished */
1685 :
1686 6081 : decode_res = fd_tls_decode_finished( &server_fin, wire, (ulong)(wire_end-wire) );
1687 6081 : if( FD_UNLIKELY( decode_res<0L ) )
1688 0 : return fd_tls_alert( &hs->base, (uint)(-decode_res), FD_TLS_REASON_FINI_PARSE );
1689 6081 : wire += (ulong)decode_res;
1690 :
1691 6081 : read_sz = (ulong)(wire - record);
1692 6081 : } while(0);
1693 :
1694 : /* Record ServerFinished */
1695 :
1696 6081 : fd_sha256_append( &hs->transcript, record, read_sz );
1697 :
1698 : /* Verify that client and server's transcripts match */
1699 :
1700 6081 : int match = 0;
1701 200673 : for( ulong i=0; i<32UL; i++ ) {
1702 194592 : match |= server_fin.verify[i] ^ server_finished_expected[i];
1703 194592 : }
1704 6081 : if( FD_UNLIKELY( match!=0 ) )
1705 0 : return fd_tls_alert( &hs->base, FD_TLS_ALERT_DECRYPT_ERROR, FD_TLS_REASON_FINI_FAIL );
1706 :
1707 : /* Derive application secrets ***************************************/
1708 :
1709 : /* Export transcript hash ClientHello..ServerFinished */
1710 :
1711 6081 : transcript_clone = hs->transcript;
1712 6081 : fd_sha256_fini( &transcript_clone, transcript_hash );
1713 :
1714 : /* Derive client/server application secrets */
1715 :
1716 6081 : uchar client_app_secret[ 32UL ];
1717 6081 : fd_tls_hkdf_expand_label( client_app_secret, 32UL,
1718 6081 : hs->master_secret,
1719 6081 : "c ap traffic", 12UL,
1720 6081 : transcript_hash, 32UL );
1721 :
1722 6081 : uchar server_app_secret[ 32UL ];
1723 6081 : fd_tls_hkdf_expand_label( server_app_secret, 32UL,
1724 6081 : hs->master_secret,
1725 6081 : "s ap traffic", 12UL,
1726 6081 : transcript_hash, 32UL );
1727 :
1728 : /* Call back with application secrets */
1729 :
1730 6081 : client->secrets_fn( hs,
1731 6081 : /* read secret */ server_app_secret,
1732 6081 : /* write secret */ client_app_secret,
1733 6081 : FD_TLS_LEVEL_APPLICATION );
1734 :
1735 6081 : if( hs->client_cert ) {
1736 :
1737 : /* Send client Certificate ****************************************/
1738 :
1739 : /* TODO deduplicate this */
1740 :
1741 : /* Message buffer */
1742 6078 : # define MSG_BUFSZ 512UL
1743 6078 : uchar msg_buf[ MSG_BUFSZ ];
1744 :
1745 : /* TODO: fd_tls does not support certificate_request_context.
1746 : It is an opaque string that the server may send in the cert
1747 : request. The client is supposed to echo it back in its cert
1748 : message. However, the server is not supposed to send it in the
1749 : first place, unless post-handshake auth is used (which is not
1750 : the case) */
1751 :
1752 6078 : ulong cert_msg_sz;
1753 6078 : if( hs->client_cert_rpk ) {
1754 0 : long sz = fd_tls_encode_raw_public_key( client->cert_public_key, msg_buf, MSG_BUFSZ );
1755 0 : FD_TEST( sz>=0L );
1756 0 : cert_msg_sz = (ulong)sz;
1757 6078 : } else if( client->cert_x509_sz ) {
1758 : /* TODO: Technically should check whether the server supports
1759 : X.509. There could be servers that support neither X.509 nor
1760 : raw public keys. */
1761 :
1762 6078 : long sz = fd_tls_encode_cert_x509( client->cert_x509, client->cert_x509_sz, msg_buf, MSG_BUFSZ );
1763 6078 : FD_TEST( sz>=0L );
1764 6078 : cert_msg_sz = (ulong)sz;
1765 6078 : } else {
1766 : /* TODO: Unreachable: We should have verified whether we have
1767 : an appropriate certificate in wait_cert_cr. */
1768 0 : return fd_tls_alert( &hs->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_CERT_TYPE );
1769 0 : }
1770 :
1771 : /* Send certificate message */
1772 :
1773 6078 : if( FD_UNLIKELY( !client->sendmsg_fn(
1774 6078 : hs,
1775 6078 : msg_buf, cert_msg_sz,
1776 6078 : FD_TLS_LEVEL_HANDSHAKE,
1777 6078 : /* flush */ 0 ) ) )
1778 0 : return fd_tls_alert( &hs->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_SENDMSG_FAIL );
1779 :
1780 : /* Record Certificate message in transcript hash */
1781 :
1782 6078 : fd_sha256_append( &hs->transcript, msg_buf, cert_msg_sz );
1783 :
1784 : /* Send client CertificateVerify **********************************/
1785 :
1786 6078 : long cvfy_res = fd_tls_send_cert_verify( client, &hs->base, &hs->transcript, 1 );
1787 6078 : if( FD_UNLIKELY( !!cvfy_res ) ) return cvfy_res;
1788 :
1789 6078 : # undef MSG_BUFSZ
1790 :
1791 6078 : }
1792 :
1793 : /* Send client Finished *********************************************/
1794 :
1795 6081 : struct __attribute__((packed)) {
1796 6081 : fd_tls_msg_hdr_t hdr;
1797 6081 : fd_tls_finished_t fin;
1798 6081 : } fin_rec;
1799 6081 : fin_rec.hdr = (fd_tls_msg_hdr_t){
1800 6081 : .type = FD_TLS_MSG_FINISHED,
1801 6081 : .sz = fd_uint_to_tls_u24( 0x20 )
1802 6081 : };
1803 :
1804 6081 : fd_tls_msg_hdr_bswap( &fin_rec.hdr );
1805 :
1806 : /* Export transcript hash up to this point */
1807 :
1808 6081 : fd_sha256_fini( &hs->transcript, transcript_hash );
1809 :
1810 : /* Derive "Finished" key */
1811 :
1812 6081 : uchar client_finished_key[ 32 ];
1813 6081 : fd_tls_hkdf_expand_label( client_finished_key, 32UL,
1814 6081 : hs->client_hs_secret,
1815 6081 : "finished", 8UL,
1816 6081 : NULL, 0UL );
1817 :
1818 : /* Derive "Finished" verify data */
1819 :
1820 6081 : fd_hmac_sha256( /* data */ transcript_hash, 32UL,
1821 6081 : /* salt */ client_finished_key, 32UL,
1822 6081 : /* out */ fin_rec.fin.verify );
1823 :
1824 : /* Send client Finished message */
1825 :
1826 6081 : if( FD_UNLIKELY( !client->sendmsg_fn(
1827 6081 : hs,
1828 6081 : &fin_rec, sizeof(fin_rec),
1829 6081 : FD_TLS_LEVEL_HANDSHAKE,
1830 6081 : /* flush */ 1 ) ) )
1831 0 : return fd_tls_alert( &hs->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_SENDMSG_FAIL );
1832 :
1833 6081 : hs->base.state = FD_TLS_HS_CONNECTED;
1834 6081 : return (long)read_sz;
1835 6081 : }
1836 :
1837 : char const *
1838 0 : fd_tls_alert_cstr( uint alert ) {
1839 0 : switch( alert ) {
1840 0 : case FD_TLS_ALERT_UNEXPECTED_MESSAGE:
1841 0 : return "unexpected message";
1842 0 : case FD_TLS_ALERT_BAD_RECORD_MAC:
1843 0 : return "bad record MAC";
1844 0 : case FD_TLS_ALERT_RECORD_OVERFLOW:
1845 0 : return "record overflow";
1846 0 : case FD_TLS_ALERT_HANDSHAKE_FAILURE:
1847 0 : return "handshake failure";
1848 0 : case FD_TLS_ALERT_BAD_CERTIFICATE:
1849 0 : return "bad certificate";
1850 0 : case FD_TLS_ALERT_UNSUPPORTED_CERTIFICATE:
1851 0 : return "unsupported certificate";
1852 0 : case FD_TLS_ALERT_CERTIFICATE_REVOKED:
1853 0 : return "certificate revoked";
1854 0 : case FD_TLS_ALERT_CERTIFICATE_EXPIRED:
1855 0 : return "certificate expired";
1856 0 : case FD_TLS_ALERT_CERTIFICATE_UNKNOWN:
1857 0 : return "certificate unknown";
1858 0 : case FD_TLS_ALERT_ILLEGAL_PARAMETER:
1859 0 : return "illegal parameter";
1860 0 : case FD_TLS_ALERT_UNKNOWN_CA:
1861 0 : return "unknown CA";
1862 0 : case FD_TLS_ALERT_ACCESS_DENIED:
1863 0 : return "access denied";
1864 0 : case FD_TLS_ALERT_DECODE_ERROR:
1865 0 : return "decode error";
1866 0 : case FD_TLS_ALERT_DECRYPT_ERROR:
1867 0 : return "decrypt error";
1868 0 : case FD_TLS_ALERT_PROTOCOL_VERSION:
1869 0 : return "unsupported protocol version";
1870 0 : case FD_TLS_ALERT_INSUFFICIENT_SECURITY:
1871 0 : return "insufficient security";
1872 0 : case FD_TLS_ALERT_INTERNAL_ERROR:
1873 0 : return "internal error";
1874 0 : case FD_TLS_ALERT_INAPPROPRIATE_FALLBACK:
1875 0 : return "inappropriate fallback";
1876 0 : case FD_TLS_ALERT_USER_CANCELED:
1877 0 : return "user canceled";
1878 0 : case FD_TLS_ALERT_MISSING_EXTENSION:
1879 0 : return "missing extension";
1880 0 : case FD_TLS_ALERT_UNSUPPORTED_EXTENSION:
1881 0 : return "unsupported extension";
1882 0 : case FD_TLS_ALERT_UNRECOGNIZED_NAME:
1883 0 : return "unrecognized name";
1884 0 : case FD_TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE:
1885 0 : return "bad certificate status response";
1886 0 : case FD_TLS_ALERT_UNKNOWN_PSK_IDENTITY:
1887 0 : return "unknown PSK identity";
1888 0 : case FD_TLS_ALERT_CERTIFICATE_REQUIRED:
1889 0 : return "certificate required";
1890 0 : case FD_TLS_ALERT_NO_APPLICATION_PROTOCOL:
1891 0 : return "no application protocol";
1892 0 : default:
1893 0 : FD_LOG_WARNING(( "Missing fd_tls_alert_cstr code for %u (memory corruption?)", alert ));
1894 0 : return "unknown alert";
1895 : /* TODO add the other alert codes */
1896 0 : }
1897 0 : }
1898 :
1899 : char const *
1900 0 : fd_tls_reason_cstr( uint reason ) {
1901 0 : switch( reason ) {
1902 0 : case FD_TLS_REASON_ILLEGAL_STATE:
1903 0 : return "illegal handshake state ID (memory corruption?)";
1904 0 : case FD_TLS_REASON_SENDMSG_FAIL:
1905 0 : return "sendmsg callback failed";
1906 0 : case FD_TLS_REASON_WRONG_ENC_LVL:
1907 0 : return "wrong encryption level";
1908 0 : case FD_TLS_REASON_RAND_FAIL:
1909 0 : return "rand function failed";
1910 0 : case FD_TLS_REASON_CH_EXPECTED:
1911 0 : return "expected ClientHello, but got other message type";
1912 0 : case FD_TLS_REASON_CH_PARSE:
1913 0 : return "failed to decode ClientHello";
1914 0 : case FD_TLS_REASON_CH_ENCODE:
1915 0 : return "failed to encode ClientHello";
1916 0 : case FD_TLS_REASON_CH_NEG_VER:
1917 0 : return "unsupported TLS version (fd_tls only supports TLS 1.3)";
1918 0 : case FD_TLS_REASON_CH_NEG_KX:
1919 0 : return "ClientHello did not advertise X25519 as a supported key exchange alg";
1920 0 : case FD_TLS_REASON_CH_NEG_SIG:
1921 0 : return "ClientHello did not advertise Ed25519 as a supported signature alg";
1922 0 : case FD_TLS_REASON_CH_NEG_CIPHER:
1923 0 : return "ClientHello did not advertise AES-128-GCM as a supported cipher suite";
1924 0 : case FD_TLS_REASON_CH_NO_QUIC:
1925 0 : return "client does not support QUIC (missing QUIC transport params)";
1926 0 : case FD_TLS_REASON_CH_RETRY_KS:
1927 0 : return "client didn't provide an X25519 key share even after a RetryHelloRequest";
1928 0 : case FD_TLS_REASON_X25519_FAIL:
1929 0 : return "X25519 key exchange failed";
1930 0 : case FD_TLS_REASON_NO_X509:
1931 0 : return "peer requested X.509 cert, but we don't have one";
1932 0 : case FD_TLS_REASON_WRONG_PUBKEY:
1933 0 : return "peer identity does not match expected public key";
1934 0 : case FD_TLS_REASON_ED25519_FAIL:
1935 0 : return "Ed25519 signature verification failed";
1936 0 : case FD_TLS_REASON_FINI_FAIL:
1937 0 : return "unexpected 'Finished' data (transcript hash fail)";
1938 0 : case FD_TLS_REASON_QUIC_TP_OVERSZ:
1939 0 : return "buffer overflow in QUIC transport param handling (user bug)";
1940 0 : case FD_TLS_REASON_EE_NO_QUIC:
1941 0 : return "server does not support QUIC (missing QUIC transport params)";
1942 0 : case FD_TLS_REASON_X509_PARSE:
1943 0 : return "X.509 cert parse failed";
1944 0 : case FD_TLS_REASON_SPKI_PARSE:
1945 0 : return "Raw public key parse failed";
1946 0 : case FD_TLS_REASON_CV_EXPECTED:
1947 0 : return "expected CertificateVerify, but got other message type";
1948 0 : case FD_TLS_REASON_CV_SIGALG:
1949 0 : return "peer CertificateVerify contains uses incorrect signature algorithm";
1950 0 : case FD_TLS_REASON_FINI_PARSE:
1951 0 : return "failed to parse 'Finished' message";
1952 0 : case FD_TLS_REASON_SH_EXPECTED:
1953 0 : return "expected ServerHello, but got other message type";
1954 0 : case FD_TLS_REASON_SH_PARSE:
1955 0 : return "failed to decode ServerHello";
1956 0 : case FD_TLS_REASON_SH_ENCODE:
1957 0 : return "failed to encode ServerHello";
1958 0 : case FD_TLS_REASON_EE_EXPECTED:
1959 0 : return "expected EncryptedExtensions, but got other message type";
1960 0 : case FD_TLS_REASON_EE_PARSE:
1961 0 : return "failed to decode EncryptedExtensions";
1962 0 : case FD_TLS_REASON_EE_ENCODE:
1963 0 : return "failed to encode EncryptedExtensions";
1964 0 : case FD_TLS_REASON_CERT_TYPE:
1965 0 : return "unsupported certificate type";
1966 0 : case FD_TLS_REASON_CERT_EXPECTED:
1967 0 : return "expected Certificate, but got other message type";
1968 0 : case FD_TLS_REASON_CERT_PARSE:
1969 0 : return "failed to decode Certificate";
1970 0 : case FD_TLS_REASON_FINI_EXPECTED:
1971 0 : return "expected Finished, but got other message type";
1972 0 : case FD_TLS_REASON_CERT_CR_EXPECTED:
1973 0 : return "expected Certificate or CertificateRequest, but got other message type";
1974 0 : case FD_TLS_REASON_CERT_CR_PARSE:
1975 0 : return "failed to decode Certificate or CertificateRequest";
1976 0 : case FD_TLS_REASON_CERT_CHAIN_EMPTY:
1977 0 : return "peer did not provide a certificate";
1978 0 : case FD_TLS_REASON_CERT_CHAIN_PARSE:
1979 0 : return "invalid peer cert chain";
1980 0 : case FD_TLS_REASON_CV_PARSE:
1981 0 : return "failed to decode CertificateVerify";
1982 0 : case FD_TLS_REASON_CV_ENCODE:
1983 0 : return "failed to encode CertificateVerify";
1984 0 : case FD_TLS_REASON_ALPN_PARSE:
1985 0 : return "failed to decode ALPN extension";
1986 0 : case FD_TLS_REASON_ALPN_NEG:
1987 0 : return "ALPN negotiation failed";
1988 0 : case FD_TLS_REASON_NO_ALPN:
1989 0 : return "peer did not send ALPN extension";
1990 0 : default:
1991 0 : FD_LOG_WARNING(( "Missing fd_tls_reason_cstr code for %u (memory corruption?)", reason ));
1992 0 : __attribute__((fallthrough));
1993 : /* TODO need to add a lot more error reason codes */
1994 0 : case FD_TLS_REASON_NULL:
1995 0 : return "unknown reason";
1996 0 : }
1997 0 : }
|