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