1- use std:: str;
1+ use std:: { io :: Write , str} ;
22
33use aws_lc_rs:: {
44 agreement:: { self , EphemeralPrivateKey , UnparsedPublicKey , X25519 } ,
@@ -15,6 +15,7 @@ use crate::{
1515} ;
1616
1717pub ( crate ) struct EcdhKeyExchange {
18+ cookie : [ u8 ; 16 ] ,
1819 /// The current session id or `None` if this is the initial key exchange.
1920 session_id : Option < digest:: Digest > ,
2021}
@@ -138,6 +139,32 @@ impl EcdhKeyExchange {
138139 return Err ( ( ) ) ;
139140 }
140141
142+ if std:: env:: var ( "OXISH_ENABLE_KEYLOG" ) . as_deref ( ) == Ok ( "1" ) {
143+ #[ allow( clippy:: assertions_on_constants) ]
144+ {
145+ assert ! ( cfg!( debug_assertions) ) ;
146+ }
147+ eprintln ! ( "Logging shared secret to ssh_keylog file!" ) ;
148+ std:: fs:: OpenOptions :: new ( )
149+ . create ( true )
150+ . append ( true )
151+ . open ( "ssh_keylog" )
152+ . unwrap ( )
153+ . write_all (
154+ format ! (
155+ "{:032x} SHARED_SECRET {}\n " ,
156+ u128 :: from_be_bytes( self . cookie) ,
157+ shared_secret
158+ . iter( )
159+ . map( |& byte| format!( "{byte:02X}" ) )
160+ . collect:: <Vec <_>>( )
161+ . join( "" )
162+ )
163+ . as_bytes ( ) ,
164+ )
165+ . unwrap ( ) ;
166+ }
167+
141168 // The first exchange hash is used as session id.
142169 let session_id = self . session_id . as_ref ( ) . unwrap_or ( & exchange_hash) ;
143170 let derivation = KeyDerivation {
@@ -325,6 +352,8 @@ impl KeyExchange {
325352 }
326353 } ;
327354
355+ let cookie = key_exchange_init. cookie ;
356+
328357 if let Err ( error) = conn
329358 . stream_write
330359 . write_packet ( & key_exchange_init, |kex_init_payload| {
@@ -354,6 +383,7 @@ impl KeyExchange {
354383 }
355384
356385 Ok ( EcdhKeyExchange {
386+ cookie,
357387 session_id : self . session_id ,
358388 } )
359389 }
0 commit comments