@@ -7,10 +7,10 @@ use core::ops::Deref;
77
88use pki_types:: ServerName ;
99
10+ use super :: reality;
1011#[ cfg( feature = "tls12" ) ]
1112use super :: tls12;
1213use super :: Tls12Resumption ;
13- use super :: reality;
1414#[ cfg( feature = "logging" ) ]
1515use crate :: bs_debug;
1616use crate :: check:: inappropriate_handshake_message;
@@ -132,7 +132,7 @@ where
132132 // Set kx_state to X25519 group for Reality
133133 let x25519_group = config
134134 . find_kx_group ( NamedGroup :: X25519 , ProtocolVersion :: TLSv1_3 )
135- . expect ( "X25519 group required for Reality" ) ;
135+ . ok_or ( Error :: General ( "X25519 group required for Reality" . into ( ) ) ) ? ;
136136 cx. common . kx_state = KxState :: Start ( x25519_group) ;
137137 None // Will be set later from reality_state
138138 } else if config. supports_version ( ProtocolVersion :: TLSv1_3 ) {
@@ -171,7 +171,7 @@ where
171171 }
172172 Some ( inner. session_id )
173173 }
174- _ => None ,
174+ _ => None :: < SessionId > ,
175175 }
176176 } else {
177177 debug ! ( "Not resuming any session" ) ;
@@ -235,6 +235,7 @@ struct ExpectServerHello {
235235 offered_key_share : Option < Box < dyn ActiveKeyExchange > > ,
236236 suite : Option < SupportedCipherSuite > ,
237237 ech_state : Option < EchState > ,
238+ reality_state : Option < reality:: RealitySessionState > ,
238239}
239240
240241struct ExpectServerHelloOrHelloRetryRequest {
@@ -552,6 +553,47 @@ where
552553 payload : HandshakePayload :: ClientHello ( chp_payload) ,
553554 } ;
554555
556+ // Compute Reality session_id BEFORE PSK binder to avoid invalidating the binder
557+ // Reality uses ClientHello with session_id=0 as AAD, so this order is safe
558+ if let Some ( ref reality) = reality_state {
559+ // Step 1: Set session_id to zero temporarily
560+ let mut buffer = Vec :: new ( ) ;
561+ match & mut chp. payload {
562+ HandshakePayload :: ClientHello ( c) => {
563+ c. session_id = SessionId {
564+ len : 32 ,
565+ data : [ 0 ; 32 ] ,
566+ } ;
567+ }
568+ _ => unreachable ! ( ) ,
569+ }
570+
571+ // Step 2: Encode ClientHello with zero session_id (for AAD)
572+ chp. encode ( & mut buffer) ;
573+
574+ // Step 3: Get HKDF-SHA256 provider
575+ let hkdf = reality:: get_hkdf_sha256_from_config ( & config. provider . cipher_suites ) ?;
576+
577+ // Step 4: Compute Reality session_id
578+ let session_id_data = reality. compute_session_id (
579+ & input. random ,
580+ & buffer,
581+ hkdf,
582+ config. time_provider . as_ref ( ) ,
583+ ) ?;
584+
585+ // Step 5: Update session_id with computed Reality value
586+ match & mut chp. payload {
587+ HandshakePayload :: ClientHello ( c) => {
588+ c. session_id = SessionId {
589+ len : 32 ,
590+ data : session_id_data,
591+ } ;
592+ }
593+ _ => unreachable ! ( ) ,
594+ }
595+ }
596+
555597 let early_key_schedule = match ( ech_state. as_mut ( ) , tls13_session) {
556598 // If we're performing ECH and resuming, then the PSK binder will have been dealt with
557599 // separately, and we need to take the early_data_key_schedule computed for the inner hello.
@@ -561,7 +603,7 @@ where
561603 . map ( |schedule| ( tls13_session. suite ( ) , schedule) ) ,
562604
563605 // When we're not doing ECH and resuming, then the PSK binder need to be filled in as
564- // normal.
606+ // normal. Reality session_id has been set above, so PSK binder will see the correct value.
565607 ( _, Some ( tls13_session) ) => Some ( (
566608 tls13_session. suite ( ) ,
567609 tls13:: fill_in_psk_binder ( & tls13_session, & transcript_buffer, & mut chp) ,
@@ -596,46 +638,6 @@ where
596638 }
597639 }
598640
599- // Compute Reality session_id if Reality is enabled
600- if let Some ( ref reality) = reality_state {
601- // Step 1: Set session_id to zero temporarily
602- let mut buffer = Vec :: new ( ) ;
603- match & mut chp. payload {
604- HandshakePayload :: ClientHello ( c) => {
605- c. session_id = SessionId {
606- len : 32 ,
607- data : [ 0 ; 32 ] ,
608- } ;
609- }
610- _ => unreachable ! ( ) ,
611- }
612-
613- // Step 2: Encode ClientHello with zero session_id
614- chp. encode ( & mut buffer) ;
615-
616- // Step 3: Get HKDF-SHA256 provider
617- let hkdf = reality:: get_hkdf_sha256_from_config ( & config. provider . cipher_suites ) ?;
618-
619- // Step 4: Compute Reality session_id
620- let session_id_data = reality. compute_session_id (
621- & input. random ,
622- & buffer,
623- hkdf,
624- config. time_provider . as_ref ( ) ,
625- ) ?;
626-
627- // Step 5: Update session_id
628- match & mut chp. payload {
629- HandshakePayload :: ClientHello ( c) => {
630- c. session_id = SessionId {
631- len : 32 ,
632- data : session_id_data,
633- } ;
634- }
635- _ => unreachable ! ( ) ,
636- }
637- }
638-
639641 let ch = Message {
640642 version : match retryreq {
641643 // <https://datatracker.ietf.org/doc/html/rfc8446#section-5.1>:
@@ -698,6 +700,7 @@ where
698700 offered_key_share : key_share,
699701 suite,
700702 ech_state,
703+ reality_state,
701704 } ;
702705
703706 Ok ( if support_tls13 && retryreq. is_none ( ) {
@@ -1266,7 +1269,7 @@ impl ExpectServerHelloOrHelloRetryRequest {
12661269 self . next . input ,
12671270 cx,
12681271 self . next . ech_state ,
1269- None , // Reality state not used in retry
1272+ self . next . reality_state ,
12701273 )
12711274 }
12721275}
0 commit comments