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