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