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 : (void)client;
1256 :
1257 6021 : if( FD_UNLIKELY( encryption_level != FD_TLS_LEVEL_HANDSHAKE ) )
1258 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_WRONG_ENC_LVL );
1259 :
1260 : /* Read EncryptedExtensions (EE) message ****************************/
1261 :
1262 6021 : fd_tls_enc_ext_t ee[1] = {0};
1263 :
1264 6021 : ulong read_sz;
1265 6021 : do {
1266 6021 : uchar const * wire = record;
1267 6021 : uchar const * const wire_end = record + record_sz;
1268 :
1269 : /* Decode message header */
1270 :
1271 6021 : fd_tls_msg_hdr_t msg_hdr = {0};
1272 6021 : long decode_res = fd_tls_decode_msg_hdr( &msg_hdr, wire, (ulong)(wire_end-wire) );
1273 6021 : if( FD_UNLIKELY( decode_res<0L ) )
1274 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_DECODE_ERROR, FD_TLS_REASON_EE_PARSE );
1275 6021 : wire += (ulong)decode_res;
1276 :
1277 6021 : if( FD_UNLIKELY( msg_hdr.type != FD_TLS_MSG_ENCRYPTED_EXT ) )
1278 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_UNEXPECTED_MESSAGE, FD_TLS_REASON_EE_EXPECTED );
1279 :
1280 : /* Decode EncryptedExtensions */
1281 :
1282 6021 : decode_res = fd_tls_decode_enc_ext( ee, wire, (ulong)(wire_end-wire) );
1283 6021 : if( FD_UNLIKELY( decode_res<0L ) )
1284 0 : return fd_tls_alert( &handshake->base, (uint)(-decode_res), FD_TLS_REASON_EE_PARSE );
1285 6021 : wire += (ulong)decode_res;
1286 :
1287 6021 : read_sz = (ulong)(wire - record);
1288 6021 : } while(0);
1289 :
1290 : /* Record EE in transcript hash */
1291 :
1292 6021 : fd_sha256_append( &handshake->transcript, record, read_sz );
1293 :
1294 6021 : switch( ee->server_cert.cert_type ) {
1295 6021 : case FD_TLS_CERTTYPE_X509:
1296 6021 : break; /* ok */
1297 0 : case FD_TLS_CERTTYPE_RAW_PUBKEY:
1298 0 : handshake->server_cert_rpk = 1;
1299 0 : break;
1300 0 : default:
1301 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_UNSUPPORTED_CERTIFICATE, FD_TLS_REASON_CERT_TYPE );
1302 6021 : }
1303 :
1304 6021 : handshake->client_cert_nox509 = 1;
1305 6021 : switch( ee->client_cert.cert_type ) {
1306 6021 : case FD_TLS_CERTTYPE_X509:
1307 6021 : handshake->client_cert_nox509 = 0;
1308 6021 : break;
1309 0 : case FD_TLS_CERTTYPE_RAW_PUBKEY:
1310 0 : handshake->client_cert_rpk = 1;
1311 0 : break;
1312 0 : default:
1313 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_UNSUPPORTED_CERTIFICATE, FD_TLS_REASON_CERT_TYPE );
1314 6021 : }
1315 :
1316 : /* QUIC mode */
1317 :
1318 6021 : if( client->quic ) {
1319 : /* QUIC transport parameters are mandatory in QUIC mode */
1320 6018 : if( FD_UNLIKELY( !ee->quic_tp.buf ) )
1321 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_MISSING_EXTENSION, FD_TLS_REASON_EE_NO_QUIC );
1322 :
1323 : /* Inform user of peer's QUIC transport parameters */
1324 6018 : client->quic_tp_peer_fn( handshake, ee->quic_tp.buf, ee->quic_tp.bufsz );
1325 6018 : }
1326 :
1327 : /* Check ALPN */
1328 :
1329 6021 : if( client->alpn_sz ) {
1330 6018 : if( FD_UNLIKELY( !ee->alpn.bufsz ) )
1331 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_MISSING_EXTENSION, FD_TLS_REASON_NO_ALPN );
1332 6018 : if( FD_UNLIKELY( ee->alpn.bufsz != client->alpn_sz ||
1333 6018 : 0!=memcmp( ee->alpn.buf, client->alpn, client->alpn_sz ) ) )
1334 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_HANDSHAKE_FAILURE, FD_TLS_REASON_ALPN_NEG );
1335 6018 : }
1336 :
1337 : /* Fail if server requested an X.509 client cert, but we can only
1338 : serve a raw public key. */
1339 :
1340 6021 : if( FD_UNLIKELY( ( !!handshake->client_cert )
1341 6021 : & ( !handshake->client_cert_rpk )
1342 6021 : & ( ( !client->cert_x509_sz )
1343 6021 : | ( !!handshake->client_cert_nox509 ) ) ) )
1344 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_UNSUPPORTED_CERTIFICATE, FD_TLS_REASON_NO_X509 );
1345 :
1346 : /* Finish up ********************************************************/
1347 :
1348 6021 : handshake->base.state = FD_TLS_HS_WAIT_CERT_CR;
1349 :
1350 6021 : return (long)read_sz;
1351 6021 : }
1352 :
1353 : static long
1354 : fd_tls_client_handle_cert_req( fd_tls_estate_cli_t * const handshake,
1355 : uchar const * const req,
1356 0 : ulong const req_sz ) {
1357 :
1358 : /* For now, just ignore the content of the certificate request.
1359 : TODO: This is obviously not compliant. */
1360 0 : (void)req; (void)req_sz;
1361 :
1362 0 : handshake->client_cert = 1;
1363 0 : handshake->base.state = FD_TLS_HS_WAIT_CERT;
1364 :
1365 0 : return (long)req_sz;
1366 0 : }
1367 :
1368 : static long
1369 : fd_tls_client_handle_cert_chain( fd_tls_estate_cli_t * const hs,
1370 : uchar const * const cert_chain,
1371 6021 : ulong const cert_chain_sz ) {
1372 : /* pubkey pinning is ...
1373 : ... enabled => check that public key matches cert
1374 : ... disabled => update the handshake's public key value based on cert */
1375 6021 : uchar const * expected_pubkey = ( hs->server_pubkey_pin) ? (hs->server_pubkey) : NULL;
1376 6021 : uchar * out_pubkey = (!hs->server_pubkey_pin) ? (hs->server_pubkey) : NULL;
1377 6021 : return fd_tls_handle_cert_chain( &hs->base, cert_chain, cert_chain_sz, expected_pubkey, out_pubkey, hs->server_cert_rpk );
1378 6021 : }
1379 :
1380 : static long
1381 : fd_tls_client_hs_wait_cert_cr( fd_tls_t const * const client,
1382 : fd_tls_estate_cli_t * const handshake,
1383 : uchar const * const record,
1384 : ulong const record_sz,
1385 6021 : uint const encryption_level ) {
1386 :
1387 6021 : (void)client;
1388 :
1389 6021 : if( FD_UNLIKELY( encryption_level != FD_TLS_LEVEL_HANDSHAKE ) )
1390 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_WRONG_ENC_LVL );
1391 :
1392 : /* Read Certificate(Request) ****************************************/
1393 :
1394 6021 : uchar next_state;
1395 :
1396 6021 : ulong read_sz;
1397 6021 : do {
1398 6021 : uchar const * wire = record;
1399 6021 : uchar const * const wire_end = record + record_sz;
1400 :
1401 : /* Decode message header */
1402 :
1403 6021 : fd_tls_msg_hdr_t msg_hdr = {0};
1404 6021 : long decode_res = fd_tls_decode_msg_hdr( &msg_hdr, wire, (ulong)(wire_end-wire) );
1405 6021 : if( FD_UNLIKELY( decode_res<0L ) )
1406 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_DECODE_ERROR, FD_TLS_REASON_CERT_CR_PARSE );
1407 6021 : wire += (ulong)decode_res;
1408 :
1409 6021 : ulong msg_sz = fd_tls_u24_to_uint( msg_hdr.sz );
1410 6021 : if( FD_UNLIKELY( msg_sz > (ulong)(wire_end-wire) ) )
1411 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_DECODE_ERROR, FD_TLS_REASON_CERT_CR_PARSE );
1412 :
1413 6021 : switch( msg_hdr.type ) {
1414 0 : case FD_TLS_MSG_CERT_REQ:
1415 0 : decode_res = fd_tls_client_handle_cert_req ( handshake, wire, msg_sz );
1416 0 : next_state = FD_TLS_HS_WAIT_CERT;
1417 0 : break;
1418 6021 : case FD_TLS_MSG_CERT:
1419 6021 : decode_res = fd_tls_client_handle_cert_chain( handshake, wire, msg_sz );
1420 6021 : next_state = FD_TLS_HS_WAIT_CV;
1421 6021 : break;
1422 0 : default:
1423 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_UNEXPECTED_MESSAGE, FD_TLS_REASON_CERT_CR_EXPECTED );
1424 6021 : }
1425 :
1426 6021 : if( FD_UNLIKELY( decode_res<0L ) )
1427 0 : return fd_tls_alert( &handshake->base, (uint)(-decode_res), FD_TLS_REASON_CERT_CR_PARSE );
1428 6021 : wire += (ulong)decode_res;
1429 :
1430 6021 : read_sz = (ulong)(wire - record);
1431 6021 : } while(0);
1432 :
1433 6021 : fd_sha256_append( &handshake->transcript, record, read_sz );
1434 :
1435 : /* Finish up ********************************************************/
1436 :
1437 6021 : handshake->base.state = ((uchar)next_state);
1438 6021 : return (long)read_sz;
1439 6021 : }
1440 :
1441 : static long
1442 : fd_tls_client_hs_wait_cert( fd_tls_t const * const client,
1443 : fd_tls_estate_cli_t * const handshake,
1444 : uchar const * const record,
1445 : ulong const record_sz,
1446 0 : uint const encryption_level ) {
1447 :
1448 0 : (void)client;
1449 :
1450 0 : if( FD_UNLIKELY( encryption_level != FD_TLS_LEVEL_HANDSHAKE ) )
1451 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_WRONG_ENC_LVL );
1452 :
1453 : /* Read Certificate *************************************************/
1454 :
1455 0 : ulong read_sz;
1456 0 : do {
1457 0 : uchar const * wire = record;
1458 0 : uchar const * const wire_end = record + record_sz;
1459 :
1460 : /* Decode message header */
1461 :
1462 0 : fd_tls_msg_hdr_t msg_hdr = {0};
1463 0 : long decode_res = fd_tls_decode_msg_hdr( &msg_hdr, wire, (ulong)(wire_end-wire) );
1464 0 : if( FD_UNLIKELY( decode_res<0L ) )
1465 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_DECODE_ERROR, FD_TLS_REASON_CERT_PARSE );
1466 0 : wire += (ulong)decode_res;
1467 :
1468 0 : if( FD_UNLIKELY( msg_hdr.type != FD_TLS_MSG_CERT ) )
1469 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_UNEXPECTED_MESSAGE, FD_TLS_REASON_CERT_EXPECTED );
1470 :
1471 0 : ulong msg_sz = fd_tls_u24_to_uint( msg_hdr.sz );
1472 0 : if( FD_UNLIKELY( msg_sz > (ulong)(wire_end-wire) ) )
1473 0 : return fd_tls_alert( &handshake->base, FD_TLS_ALERT_DECODE_ERROR, FD_TLS_REASON_CERT_CR_PARSE );
1474 :
1475 : /* Decode Certificate */
1476 :
1477 0 : decode_res = fd_tls_client_handle_cert_chain( handshake, wire, msg_sz );
1478 0 : if( FD_UNLIKELY( decode_res<0L ) )
1479 0 : return fd_tls_alert( &handshake->base, (uint)(-decode_res), FD_TLS_REASON_CERT_PARSE );
1480 0 : wire += (ulong)decode_res;
1481 :
1482 0 : read_sz = (ulong)(wire - record);
1483 0 : } while(0);
1484 :
1485 0 : fd_sha256_append( &handshake->transcript, record, read_sz );
1486 :
1487 : /* Finish up ********************************************************/
1488 :
1489 0 : handshake->base.state = (char)FD_TLS_HS_WAIT_CV;
1490 0 : return (long)read_sz;
1491 0 : }
1492 :
1493 : static long
1494 : fd_tls_client_hs_wait_cert_verify( fd_tls_t const * const client,
1495 : fd_tls_estate_cli_t * const hs,
1496 : uchar const * const record,
1497 : ulong const record_sz,
1498 6021 : uint const encryption_level ) {
1499 :
1500 6021 : (void)client;
1501 :
1502 6021 : if( FD_UNLIKELY( encryption_level != FD_TLS_LEVEL_HANDSHAKE ) )
1503 0 : return fd_tls_alert( &hs->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_WRONG_ENC_LVL );
1504 :
1505 : /* Decode incoming server CertificateVerify *************************/
1506 :
1507 6021 : long res = fd_tls_handle_cert_verify( &hs->base, &hs->transcript, record, record_sz, hs->server_pubkey, 0 );
1508 6021 : if( FD_UNLIKELY( res<0L ) ) return res;
1509 :
1510 6021 : fd_sha256_append( &hs->transcript, record, (ulong)res );
1511 :
1512 : /* Finish up ********************************************************/
1513 :
1514 6021 : hs->base.state = FD_TLS_HS_WAIT_FINISHED;
1515 6021 : return res;
1516 6021 : }
1517 :
1518 : static long
1519 : fd_tls_client_hs_wait_finished( fd_tls_t const * const client,
1520 : fd_tls_estate_cli_t * const hs,
1521 : uchar const * const record,
1522 : ulong const record_sz,
1523 6021 : uint const encryption_level ) {
1524 :
1525 6021 : if( FD_UNLIKELY( encryption_level != FD_TLS_LEVEL_HANDSHAKE ) )
1526 0 : return fd_tls_alert( &hs->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_WRONG_ENC_LVL );
1527 :
1528 : /* Export transcript hash ClientHello..CertificateVerify */
1529 :
1530 6021 : fd_sha256_t transcript_clone = hs->transcript;
1531 6021 : uchar transcript_hash[ 32 ];
1532 6021 : fd_sha256_fini( &transcript_clone, transcript_hash );
1533 :
1534 : /* Derive "Finished" key */
1535 :
1536 6021 : uchar server_finished_key[ 32 ];
1537 6021 : fd_tls_hkdf_expand_label( server_finished_key, 32UL,
1538 6021 : hs->server_hs_secret,
1539 6021 : "finished", 8UL,
1540 6021 : NULL, 0UL );
1541 :
1542 : /* Derive "Finished" verify data */
1543 :
1544 6021 : uchar server_finished_expected[ 32 ];
1545 6021 : fd_hmac_sha256( /* data */ transcript_hash, 32UL,
1546 6021 : /* salt */ server_finished_key, 32UL,
1547 6021 : /* out */ server_finished_expected );
1548 :
1549 : /* Read ServerFinished **********************************************/
1550 :
1551 6021 : fd_tls_finished_t server_fin = {0};
1552 :
1553 6021 : ulong read_sz;
1554 6021 : do {
1555 6021 : uchar const * wire = record;
1556 6021 : uchar const * const wire_end = record + record_sz;
1557 :
1558 : /* Decode message header */
1559 :
1560 6021 : fd_tls_msg_hdr_t msg_hdr = {0};
1561 6021 : long decode_res = fd_tls_decode_msg_hdr( &msg_hdr, wire, (ulong)(wire_end-wire) );
1562 6021 : if( FD_UNLIKELY( decode_res<0L ) )
1563 0 : return fd_tls_alert( &hs->base, FD_TLS_ALERT_DECODE_ERROR, FD_TLS_REASON_FINI_PARSE );
1564 6021 : wire += (ulong)decode_res;
1565 :
1566 6021 : if( FD_UNLIKELY( msg_hdr.type != FD_TLS_MSG_FINISHED ) )
1567 0 : return fd_tls_alert( &hs->base, FD_TLS_ALERT_UNEXPECTED_MESSAGE, FD_TLS_REASON_FINI_EXPECTED );
1568 :
1569 : /* Decode server Finished */
1570 :
1571 6021 : decode_res = fd_tls_decode_finished( &server_fin, wire, (ulong)(wire_end-wire) );
1572 6021 : if( FD_UNLIKELY( decode_res<0L ) )
1573 0 : return fd_tls_alert( &hs->base, (uint)(-decode_res), FD_TLS_REASON_FINI_PARSE );
1574 6021 : wire += (ulong)decode_res;
1575 :
1576 6021 : read_sz = (ulong)(wire - record);
1577 6021 : } while(0);
1578 :
1579 : /* Record ServerFinished */
1580 :
1581 6021 : fd_sha256_append( &hs->transcript, record, read_sz );
1582 :
1583 : /* Verify that client and server's transcripts match */
1584 :
1585 6021 : int match = 0;
1586 198693 : for( ulong i=0; i<32UL; i++ ) {
1587 192672 : match |= server_fin.verify[i] ^ server_finished_expected[i];
1588 192672 : }
1589 6021 : if( FD_UNLIKELY( match!=0 ) )
1590 0 : return fd_tls_alert( &hs->base, FD_TLS_ALERT_DECRYPT_ERROR, FD_TLS_REASON_FINI_FAIL );
1591 :
1592 : /* Derive application secrets ***************************************/
1593 :
1594 : /* Export transcript hash ClientHello..ServerFinished */
1595 :
1596 6021 : transcript_clone = hs->transcript;
1597 6021 : fd_sha256_fini( &transcript_clone, transcript_hash );
1598 :
1599 : /* Derive client/server application secrets */
1600 :
1601 6021 : uchar client_app_secret[ 32UL ];
1602 6021 : fd_tls_hkdf_expand_label( client_app_secret, 32UL,
1603 6021 : hs->master_secret,
1604 6021 : "c ap traffic", 12UL,
1605 6021 : transcript_hash, 32UL );
1606 :
1607 6021 : uchar server_app_secret[ 32UL ];
1608 6021 : fd_tls_hkdf_expand_label( server_app_secret, 32UL,
1609 6021 : hs->master_secret,
1610 6021 : "s ap traffic", 12UL,
1611 6021 : transcript_hash, 32UL );
1612 :
1613 : /* Call back with application secrets */
1614 :
1615 6021 : client->secrets_fn( hs,
1616 6021 : /* read secret */ server_app_secret,
1617 6021 : /* write secret */ client_app_secret,
1618 6021 : FD_TLS_LEVEL_APPLICATION );
1619 :
1620 6021 : if( hs->client_cert ) {
1621 :
1622 : /* Send client Certificate ****************************************/
1623 :
1624 : /* TODO deduplicate this */
1625 :
1626 : /* Message buffer */
1627 0 : # define MSG_BUFSZ 512UL
1628 0 : uchar msg_buf[ MSG_BUFSZ ];
1629 :
1630 : /* TODO: fd_tls does not support certificate_request_context.
1631 : It is an opaque string that the server may send in the cert
1632 : request. The client is supposed to echo it back in its cert
1633 : message. However, the server is not supposed to send it in the
1634 : first place, unless post-handshake auth is used (which is not
1635 : the case) */
1636 :
1637 0 : ulong cert_msg_sz;
1638 0 : if( hs->client_cert_rpk ) {
1639 0 : long sz = fd_tls_encode_raw_public_key( client->cert_public_key, msg_buf, MSG_BUFSZ );
1640 0 : FD_TEST( sz>=0L );
1641 0 : cert_msg_sz = (ulong)sz;
1642 0 : } else if( client->cert_x509_sz ) {
1643 : /* TODO: Technically should check whether the server supports
1644 : X.509. There could be servers that support neither X.509 nor
1645 : raw public keys. */
1646 :
1647 0 : long sz = fd_tls_encode_cert_x509( client->cert_x509, client->cert_x509_sz, msg_buf, MSG_BUFSZ );
1648 0 : FD_TEST( sz>=0L );
1649 0 : cert_msg_sz = (ulong)sz;
1650 0 : } else {
1651 : /* TODO: Unreachable: We should have verified whether we have
1652 : an appropriate certificate in wait_cert_cr. */
1653 0 : return fd_tls_alert( &hs->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_CERT_TYPE );
1654 0 : }
1655 :
1656 : /* Send certificate message */
1657 :
1658 0 : if( FD_UNLIKELY( !client->sendmsg_fn(
1659 0 : hs,
1660 0 : msg_buf, cert_msg_sz,
1661 0 : FD_TLS_LEVEL_HANDSHAKE,
1662 0 : /* flush */ 0 ) ) )
1663 0 : return fd_tls_alert( &hs->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_SENDMSG_FAIL );
1664 :
1665 : /* Record Certificate message in transcript hash */
1666 :
1667 0 : fd_sha256_append( &hs->transcript, msg_buf, cert_msg_sz );
1668 :
1669 : /* Send client CertificateVerify **********************************/
1670 :
1671 0 : long cvfy_res = fd_tls_send_cert_verify( client, &hs->base, &hs->transcript, 1 );
1672 0 : if( FD_UNLIKELY( !!cvfy_res ) ) return cvfy_res;
1673 :
1674 0 : # undef MSG_BUFSZ
1675 :
1676 0 : }
1677 :
1678 : /* Send client Finished *********************************************/
1679 :
1680 6021 : struct __attribute__((packed)) {
1681 6021 : fd_tls_msg_hdr_t hdr;
1682 6021 : fd_tls_finished_t fin;
1683 6021 : } fin_rec;
1684 6021 : fin_rec.hdr = (fd_tls_msg_hdr_t){
1685 6021 : .type = FD_TLS_MSG_FINISHED,
1686 6021 : .sz = fd_uint_to_tls_u24( 0x20 )
1687 6021 : };
1688 :
1689 6021 : fd_tls_msg_hdr_bswap( &fin_rec.hdr );
1690 :
1691 : /* Export transcript hash up to this point */
1692 :
1693 6021 : fd_sha256_fini( &hs->transcript, transcript_hash );
1694 :
1695 : /* Derive "Finished" key */
1696 :
1697 6021 : uchar client_finished_key[ 32 ];
1698 6021 : fd_tls_hkdf_expand_label( client_finished_key, 32UL,
1699 6021 : hs->client_hs_secret,
1700 6021 : "finished", 8UL,
1701 6021 : NULL, 0UL );
1702 :
1703 : /* Derive "Finished" verify data */
1704 :
1705 6021 : fd_hmac_sha256( /* data */ transcript_hash, 32UL,
1706 6021 : /* salt */ client_finished_key, 32UL,
1707 6021 : /* out */ fin_rec.fin.verify );
1708 :
1709 : /* Send client Finished message */
1710 :
1711 6021 : if( FD_UNLIKELY( !client->sendmsg_fn(
1712 6021 : hs,
1713 6021 : &fin_rec, sizeof(fin_rec),
1714 6021 : FD_TLS_LEVEL_HANDSHAKE,
1715 6021 : /* flush */ 1 ) ) )
1716 0 : return fd_tls_alert( &hs->base, FD_TLS_ALERT_INTERNAL_ERROR, FD_TLS_REASON_SENDMSG_FAIL );
1717 :
1718 6021 : hs->base.state = FD_TLS_HS_CONNECTED;
1719 6021 : return (long)read_sz;
1720 6021 : }
1721 :
1722 : FD_FN_PURE char const *
1723 0 : fd_tls_alert_cstr( uint alert ) {
1724 0 : switch( alert ) {
1725 0 : case FD_TLS_ALERT_UNEXPECTED_MESSAGE:
1726 0 : return "unexpected message";
1727 0 : case FD_TLS_ALERT_BAD_RECORD_MAC:
1728 0 : return "bad record MAC";
1729 0 : case FD_TLS_ALERT_RECORD_OVERFLOW:
1730 0 : return "record overflow";
1731 0 : case FD_TLS_ALERT_HANDSHAKE_FAILURE:
1732 0 : return "handshake failure";
1733 0 : case FD_TLS_ALERT_BAD_CERTIFICATE:
1734 0 : return "bad certificate";
1735 0 : case FD_TLS_ALERT_UNSUPPORTED_CERTIFICATE:
1736 0 : return "unsupported certificate";
1737 0 : case FD_TLS_ALERT_CERTIFICATE_REVOKED:
1738 0 : return "certificate revoked";
1739 0 : case FD_TLS_ALERT_CERTIFICATE_EXPIRED:
1740 0 : return "certificate expired";
1741 0 : case FD_TLS_ALERT_CERTIFICATE_UNKNOWN:
1742 0 : return "certificate unknown";
1743 0 : case FD_TLS_ALERT_ILLEGAL_PARAMETER:
1744 0 : return "illegal parameter";
1745 0 : case FD_TLS_ALERT_UNKNOWN_CA:
1746 0 : return "unknown CA";
1747 0 : case FD_TLS_ALERT_ACCESS_DENIED:
1748 0 : return "access denied";
1749 0 : case FD_TLS_ALERT_DECODE_ERROR:
1750 0 : return "decode error";
1751 0 : case FD_TLS_ALERT_DECRYPT_ERROR:
1752 0 : return "decrypt error";
1753 0 : case FD_TLS_ALERT_PROTOCOL_VERSION:
1754 0 : return "unsupported protocol version";
1755 0 : case FD_TLS_ALERT_INSUFFICIENT_SECURITY:
1756 0 : return "insufficient security";
1757 0 : case FD_TLS_ALERT_INTERNAL_ERROR:
1758 0 : return "internal error";
1759 0 : case FD_TLS_ALERT_INAPPROPRIATE_FALLBACK:
1760 0 : return "inappropriate fallback";
1761 0 : case FD_TLS_ALERT_USER_CANCELED:
1762 0 : return "user canceled";
1763 0 : case FD_TLS_ALERT_MISSING_EXTENSION:
1764 0 : return "missing extension";
1765 0 : case FD_TLS_ALERT_UNSUPPORTED_EXTENSION:
1766 0 : return "unsupported extension";
1767 0 : case FD_TLS_ALERT_UNRECOGNIZED_NAME:
1768 0 : return "unrecognized name";
1769 0 : case FD_TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE:
1770 0 : return "bad certificate status response";
1771 0 : case FD_TLS_ALERT_UNKNOWN_PSK_IDENTITY:
1772 0 : return "unknown PSK identity";
1773 0 : case FD_TLS_ALERT_CERTIFICATE_REQUIRED:
1774 0 : return "certificate required";
1775 0 : case FD_TLS_ALERT_NO_APPLICATION_PROTOCOL:
1776 0 : return "no application protocol";
1777 0 : default:
1778 0 : FD_LOG_WARNING(( "Missing fd_tls_alert_cstr code for %u (memory corruption?)", alert ));
1779 0 : return "unknown alert";
1780 : /* TODO add the other alert codes */
1781 0 : }
1782 0 : }
1783 :
1784 : FD_FN_PURE char const *
1785 0 : fd_tls_reason_cstr( uint reason ) {
1786 0 : switch( reason ) {
1787 0 : case FD_TLS_REASON_ILLEGAL_STATE:
1788 0 : return "illegal handshake state ID (memory corruption?)";
1789 0 : case FD_TLS_REASON_SENDMSG_FAIL:
1790 0 : return "sendmsg callback failed";
1791 0 : case FD_TLS_REASON_WRONG_ENC_LVL:
1792 0 : return "wrong encryption level";
1793 0 : case FD_TLS_REASON_RAND_FAIL:
1794 0 : return "rand function failed";
1795 0 : case FD_TLS_REASON_CH_EXPECTED:
1796 0 : return "expected ClientHello, but got other message type";
1797 0 : case FD_TLS_REASON_CH_PARSE:
1798 0 : return "failed to decode ClientHello";
1799 0 : case FD_TLS_REASON_CH_ENCODE:
1800 0 : return "failed to encode ClientHello";
1801 0 : case FD_TLS_REASON_CH_NEG_VER:
1802 0 : return "unsupported TLS version (fd_tls only supports TLS 1.3)";
1803 0 : case FD_TLS_REASON_CH_NEG_KX:
1804 0 : return "ClientHello did not advertise X25519 as a supported key exchange alg";
1805 0 : case FD_TLS_REASON_CH_NEG_SIG:
1806 0 : return "ClientHello did not advertise Ed25519 as a supported signature alg";
1807 0 : case FD_TLS_REASON_CH_NEG_CIPHER:
1808 0 : return "ClientHello did not advertise AES-128-GCM as a supported cipher suite";
1809 0 : case FD_TLS_REASON_CH_NO_QUIC:
1810 0 : return "client does not support QUIC (missing QUIC transport params)";
1811 0 : case FD_TLS_REASON_CH_RETRY_KS:
1812 0 : return "client didn't provide an X25519 key share even after a RetryHelloRequest";
1813 0 : case FD_TLS_REASON_X25519_FAIL:
1814 0 : return "X25519 key exchange failed";
1815 0 : case FD_TLS_REASON_NO_X509:
1816 0 : return "peer requested X.509 cert, but we don't have one";
1817 0 : case FD_TLS_REASON_WRONG_PUBKEY:
1818 0 : return "peer identity does not match expected public key";
1819 0 : case FD_TLS_REASON_ED25519_FAIL:
1820 0 : return "Ed25519 signature verification failed";
1821 0 : case FD_TLS_REASON_FINI_FAIL:
1822 0 : return "unexpected 'Finished' data (transcript hash fail)";
1823 0 : case FD_TLS_REASON_QUIC_TP_OVERSZ:
1824 0 : return "buffer overflow in QUIC transport param handling (user bug)";
1825 0 : case FD_TLS_REASON_EE_NO_QUIC:
1826 0 : return "server does not support QUIC (missing QUIC transport params)";
1827 0 : case FD_TLS_REASON_X509_PARSE:
1828 0 : return "X.509 cert parse failed";
1829 0 : case FD_TLS_REASON_SPKI_PARSE:
1830 0 : return "Raw public key parse failed";
1831 0 : case FD_TLS_REASON_CV_EXPECTED:
1832 0 : return "expected CertificateVerify, but got other message type";
1833 0 : case FD_TLS_REASON_CV_SIGALG:
1834 0 : return "peer CertificateVerify contains uses incorrect signature algorithm";
1835 0 : case FD_TLS_REASON_FINI_PARSE:
1836 0 : return "failed to parse 'Finished' message";
1837 0 : case FD_TLS_REASON_SH_EXPECTED:
1838 0 : return "expected ServerHello, but got other message type";
1839 0 : case FD_TLS_REASON_SH_PARSE:
1840 0 : return "failed to decode ServerHello";
1841 0 : case FD_TLS_REASON_SH_ENCODE:
1842 0 : return "failed to encode ServerHello";
1843 0 : case FD_TLS_REASON_EE_EXPECTED:
1844 0 : return "expected EncryptedExtensions, but got other message type";
1845 0 : case FD_TLS_REASON_EE_PARSE:
1846 0 : return "failed to decode EncryptedExtensions";
1847 0 : case FD_TLS_REASON_EE_ENCODE:
1848 0 : return "failed to encode EncryptedExtensions";
1849 0 : case FD_TLS_REASON_CERT_TYPE:
1850 0 : return "unsupported certificate type";
1851 0 : case FD_TLS_REASON_CERT_EXPECTED:
1852 0 : return "expected Certificate, but got other message type";
1853 0 : case FD_TLS_REASON_CERT_PARSE:
1854 0 : return "failed to decode Certificate";
1855 0 : case FD_TLS_REASON_FINI_EXPECTED:
1856 0 : return "expected Finished, but got other message type";
1857 0 : case FD_TLS_REASON_CERT_CR_EXPECTED:
1858 0 : return "expected Certificate or CertificateRequest, but got other message type";
1859 0 : case FD_TLS_REASON_CERT_CR_PARSE:
1860 0 : return "failed to decode Certificate or CertificateRequest";
1861 0 : case FD_TLS_REASON_CERT_CHAIN_EMPTY:
1862 0 : return "peer did not provide a certificate";
1863 0 : case FD_TLS_REASON_CERT_CHAIN_PARSE:
1864 0 : return "invalid peer cert chain";
1865 0 : case FD_TLS_REASON_CV_PARSE:
1866 0 : return "failed to decode CertificateVerify";
1867 0 : case FD_TLS_REASON_CV_ENCODE:
1868 0 : return "failed to encode CertificateVerify";
1869 0 : case FD_TLS_REASON_ALPN_PARSE:
1870 0 : return "failed to decode ALPN extension";
1871 0 : case FD_TLS_REASON_ALPN_NEG:
1872 0 : return "ALPN negotiation failed";
1873 0 : case FD_TLS_REASON_NO_ALPN:
1874 0 : return "peer did not send ALPN extension";
1875 0 : default:
1876 0 : FD_LOG_WARNING(( "Missing fd_tls_reason_cstr code for %u (memory corruption?)", reason ));
1877 0 : __attribute__((fallthrough));
1878 : /* TODO need to add a lot more error reason codes */
1879 0 : case FD_TLS_REASON_NULL:
1880 0 : return "unknown reason";
1881 0 : }
1882 0 : }
|