@@ -19,6 +19,7 @@ use tellers_mtproto_session::{Clock, Snapshot};
1919use tellers_mtproto_transport:: { Connection , Framing , PaddedIntermediate } ;
2020
2121use crate :: MtprotoError ;
22+ use zeroize:: Zeroize ;
2223
2324const PROD_RSA_PEM : & str = "-----BEGIN RSA PUBLIC KEY-----\n \
2425 MIIBCgKCAQEA6LszBcC1LGzyr992NzE0ieY+BSaOW622Aa9Bd4ZHLl+TuFQ4lo4g\n \
@@ -129,6 +130,15 @@ struct AuthAdapter {
129130 g_b : Option < Vec < u8 > > ,
130131 auth_key : Option < Vec < u8 > > ,
131132 expires_in : Option < i32 > ,
133+ expires_at : Option < i32 > ,
134+ time_offset_micros : Option < i64 > ,
135+ clock : fn ( ) -> i64 ,
136+ }
137+
138+ impl Drop for AuthAdapter {
139+ fn drop ( & mut self ) {
140+ self . auth_key . zeroize ( ) ;
141+ }
132142}
133143
134144impl AuthAdapter {
@@ -150,6 +160,9 @@ impl AuthAdapter {
150160 g_b : None ,
151161 auth_key : None ,
152162 expires_in : None ,
163+ expires_at : None ,
164+ time_offset_micros : None ,
165+ clock : || SystemClock . unix_micros ( ) ,
153166 } )
154167 }
155168}
@@ -272,6 +285,9 @@ impl AuthorizationAdapter for AuthAdapter {
272285 let server_nonce = self . server_nonce . clone ( ) . ok_or_else ( || {
273286 tellers_mtproto_engine:: Error :: Authorization ( "missing server_nonce" . into ( ) )
274287 } ) ?;
288+ if ok. nonce != self . nonce || ok. server_nonce != server_nonce {
289+ return Err ( tellers_mtproto_engine:: Error :: Authorization ( "DH envelope nonce mismatch" . into ( ) ) ) ;
290+ }
275291 let new_nonce = self . new_nonce . clone ( ) . ok_or_else ( || {
276292 tellers_mtproto_engine:: Error :: Authorization ( "missing new_nonce" . into ( ) )
277293 } ) ?;
@@ -299,6 +315,18 @@ impl AuthorizationAdapter for AuthAdapter {
299315 ) ) ;
300316 } ;
301317
318+ if inner. nonce != self . nonce || inner. server_nonce != server_nonce {
319+ return Err ( tellers_mtproto_engine:: Error :: Authorization ( "DH inner nonce mismatch" . into ( ) ) ) ;
320+ }
321+ let received_at = ( self . clock ) ( ) ;
322+ if inner. server_time <= 0 {
323+ return Err ( tellers_mtproto_engine:: Error :: Authorization ( "invalid DH server time" . into ( ) ) ) ;
324+ }
325+ let expires_at = self . expires_in . map ( |seconds| inner. server_time . checked_add ( seconds)
326+ . filter ( |expiry| * expiry > inner. server_time )
327+ . ok_or_else ( || tellers_mtproto_engine:: Error :: Authorization ( "invalid temporary key expiry" . into ( ) ) ) )
328+ . transpose ( ) ?;
329+
302330 use num_bigint:: BigUint ;
303331 let prime = BigUint :: from_bytes_be ( & inner. dh_prime ) ;
304332 let g_a = BigUint :: from_bytes_be ( & inner. g_a ) ;
@@ -310,7 +338,7 @@ impl AuthorizationAdapter for AuthAdapter {
310338 let prime_bytes = usize:: try_from ( prime. bits ( ) . div_ceil ( 8 ) )
311339 . unwrap_or ( 256 )
312340 . max ( 256 ) ;
313- let mut b_bytes = vec ! [ 0_u8 ; prime_bytes] ;
341+ let mut b_bytes = zeroize :: Zeroizing :: new ( vec ! [ 0_u8 ; prime_bytes] ) ;
314342 fill_random ( & mut b_bytes)
315343 . map_err ( |e| tellers_mtproto_engine:: Error :: Authorization ( e. to_string ( ) ) ) ?;
316344 let b = BigUint :: from_bytes_be ( & b_bytes) ;
@@ -322,6 +350,8 @@ impl AuthorizationAdapter for AuthAdapter {
322350 let auth_key = derive_auth_key ( & g_a, & b, & prime)
323351 . map_err ( |e| tellers_mtproto_engine:: Error :: Authorization ( e. to_string ( ) ) ) ?;
324352 self . auth_key = Some ( auth_key) ;
353+ self . expires_at = expires_at;
354+ self . time_offset_micros = Some ( ( i64:: from ( inner. server_time ) * 1_000_000 ) . saturating_sub ( received_at) ) ;
325355
326356 let client_inner = tellers_mtproto:: transport:: ClientDhInnerDataConstructor {
327357 nonce : self . nonce . clone ( ) ,
@@ -357,7 +387,7 @@ impl AuthorizationAdapter for AuthAdapter {
357387 ) -> Result < ( Vec < u8 > , i64 ) , tellers_mtproto_engine:: Error > {
358388 let answer = decode_boxed :: < SetClientDhParamsAnswer > ( response)
359389 . map_err ( |e| tellers_mtproto_engine:: Error :: Authorization ( e. to_string ( ) ) ) ?;
360- let auth_key = self . auth_key . clone ( ) . ok_or_else ( || {
390+ let auth_key = self . auth_key . as_ref ( ) . ok_or_else ( || {
361391 tellers_mtproto_engine:: Error :: Authorization ( "missing auth_key" . into ( ) )
362392 } ) ?;
363393 let new_nonce = self . new_nonce . clone ( ) . ok_or_else ( || {
@@ -368,6 +398,9 @@ impl AuthorizationAdapter for AuthAdapter {
368398 } ) ?;
369399 match answer {
370400 SetClientDhParamsAnswer :: DhGenOk ( ok) => {
401+ if ok. nonce != self . nonce || ok. server_nonce != server_nonce {
402+ return Err ( tellers_mtproto_engine:: Error :: Authorization ( "DH completion nonce mismatch" . into ( ) ) ) ;
403+ }
371404 let expected = new_nonce_hash ( & i256_to_bytes ( & new_nonce) , & auth_key, 1 ) ;
372405 let got = i128_to_bytes ( & ok. new_nonce_hash1 ) ;
373406 if got != expected {
@@ -377,13 +410,17 @@ impl AuthorizationAdapter for AuthAdapter {
377410 }
378411 let salt =
379412 initial_server_salt ( & i256_to_bytes ( & new_nonce) , & i128_to_bytes ( & server_nonce) ) ;
380- Ok ( ( auth_key, salt) )
413+ Ok ( ( self . auth_key . take ( ) . expect ( "validated auth key" ) , salt) )
381414 }
382415 _ => Err ( tellers_mtproto_engine:: Error :: Authorization (
383416 "dh_gen not ok" . into ( ) ,
384417 ) ) ,
385418 }
386419 }
420+
421+ fn time_offset_micros ( & self ) -> Option < i64 > {
422+ self . time_offset_micros
423+ }
387424}
388425
389426fn send_plain (
@@ -418,6 +455,9 @@ fn recv_plain(
418455 if n == 0 {
419456 return Err ( MtprotoError :: Message ( "connection closed" . into ( ) ) ) ;
420457 }
458+ if input. len ( ) . saturating_add ( n) > 1024 * 1024 + 4 {
459+ return Err ( MtprotoError :: Message ( "authorization response exceeds size limit" . into ( ) ) ) ;
460+ }
421461 input. extend_from_slice ( & buf[ ..n] ) ;
422462 match framing. decode ( & input) {
423463 Ok ( packet) => {
@@ -446,10 +486,11 @@ pub fn create_temp_auth_key(
446486 framing : & mut PaddedIntermediate ,
447487 snapshot : & mut Snapshot ,
448488 expires_in : i32 ,
449- ) -> Result < ( ) , MtprotoError > {
489+ ) -> Result < i32 , MtprotoError > {
450490 let mut adapter = AuthAdapter :: with_pem ( snapshot. dc_id , rsa_pem ( ) . to_string ( ) ) ?;
451491 adapter. expires_in = Some ( expires_in) ;
452- run_exchange ( adapter, conn, framing, snapshot)
492+ run_exchange ( adapter, conn, framing, snapshot) ?
493+ . ok_or_else ( || MtprotoError :: Message ( "missing temporary key expiry" . into ( ) ) )
453494}
454495
455496pub fn create_auth_key_with_pem (
@@ -459,15 +500,15 @@ pub fn create_auth_key_with_pem(
459500 pem : & str ,
460501) -> Result < ( ) , MtprotoError > {
461502 let adapter = AuthAdapter :: with_pem ( snapshot. dc_id , pem. to_string ( ) ) ?;
462- run_exchange ( adapter, conn, framing, snapshot)
503+ run_exchange ( adapter, conn, framing, snapshot) . map ( |_| ( ) )
463504}
464505
465506fn run_exchange (
466507 adapter : AuthAdapter ,
467508 conn : & mut dyn Connection ,
468509 framing : & mut PaddedIntermediate ,
469510 snapshot : & mut Snapshot ,
470- ) -> Result < ( ) , MtprotoError > {
511+ ) -> Result < Option < i32 > , MtprotoError > {
471512 let clock = SystemClock ;
472513 let mut auth = Authorization :: new ( adapter) ;
473514
@@ -498,7 +539,7 @@ fn run_exchange(
498539 if next. is_some ( ) || auth. phase ( ) != AuthorizationPhase :: Authorized {
499540 return Err ( MtprotoError :: Message ( "auth key not installed" . into ( ) ) ) ;
500541 }
501- Ok ( ( ) )
542+ Ok ( auth . into_adapter ( ) . expires_at )
502543}
503544
504545/// Padded-intermediate returns payload + 0..=15 extra bytes. Plain envelopes
0 commit comments