@@ -101,6 +101,7 @@ def __init__(self, sock):
101101 self ._pha_supported = False
102102 self .client_cert_compression_algo = None
103103 self .server_cert_compression_algo = None
104+ self .sslkeylogfile = os .environ .get ('SSLKEYLOGFILE' )
104105
105106 def keyingMaterialExporter (self , label , length = 20 ):
106107 """Return keying material as described in RFC 5705
@@ -414,7 +415,6 @@ def _handshakeClientAsync(self, srpParams=(), certParams=(), anonParams=(),
414415 session = None , settings = None , checker = None ,
415416 nextProtos = None , serverName = None , reqTack = True ,
416417 alpn = None ):
417-
418418 handshaker = self ._handshakeClientAsyncHelper (srpParams = srpParams ,
419419 certParams = certParams ,
420420 anonParams = anonParams ,
@@ -427,6 +427,10 @@ def _handshakeClientAsync(self, srpParams=(), certParams=(), anonParams=(),
427427 for result in self ._handshakeWrapperAsync (handshaker , checker ):
428428 yield result
429429
430+ # Log client random and master secret for version < TLS1.3
431+ if self .sslkeylogfile and self .version < (3 , 4 ):
432+ self ._log_session_keys ('CLIENT_RANDOM' , self ._clientRandom , self .session .masterSecret )
433+
430434
431435 def _handshakeClientAsyncHelper (self , srpParams , certParams , anonParams ,
432436 session , settings , serverName , nextProtos ,
@@ -1323,6 +1327,13 @@ def _clientTLS13Handshake(self, settings, session, clientHello,
13231327 self ._handshake_hash ,
13241328 prfName )
13251329
1330+ # TLS1.3 log Client and Server traffic secrets for SSLKEYLOGFILE
1331+ if self .sslkeylogfile :
1332+ self ._log_session_keys ('CLIENT_HANDSHAKE_TRAFFIC_SECRET' ,
1333+ clientHello .random ,
1334+ cl_handshake_traffic_secret )
1335+ self ._log_session_keys ('SERVER_HANDSHAKE_TRAFFIC_SECRET' , clientHello .random , sr_handshake_traffic_secret )
1336+
13261337 # prepare for reading encrypted messages
13271338 self ._recordLayer .calcTLS1_3PendingState (
13281339 serverHello .cipher_suite ,
@@ -1613,6 +1624,13 @@ def _clientTLS13Handshake(self, settings, session, clientHello,
16131624 bytearray (b'exp master' ),
16141625 self ._handshake_hash , prfName )
16151626
1627+
1628+ # Now that we have all the TLS1.3 secrets during the handshake, log them if necessary
1629+ if self .sslkeylogfile :
1630+ self ._log_session_keys ('EXPORTER_SECRET' , clientHello .random , exporter_master_secret )
1631+ self ._log_session_keys ('CLIENT_TRAFFIC_SECRET_0' , clientHello .random , cl_app_traffic )
1632+ self ._log_session_keys ('SERVER_TRAFFIC_SECRET_0' , clientHello .random , sr_app_traffic )
1633+
16161634 self ._recordLayer .calcTLS1_3PendingState (
16171635 serverHello .cipher_suite ,
16181636 cl_app_traffic ,
@@ -1708,7 +1726,9 @@ def _clientTLS13Handshake(self, settings, session, clientHello,
17081726 exporterMasterSecret = exporter_master_secret ,
17091727 resumptionMasterSecret = resumption_master_secret ,
17101728 # NOTE it must be a reference, not a copy!
1711- tickets = self .tickets )
1729+ tickets = self .tickets ,
1730+ cl_handshake_traffic_secret = cl_handshake_traffic_secret ,
1731+ sr_handshake_traffic_secret = sr_handshake_traffic_secret )
17121732
17131733 yield "finished" if not resuming else "resumed_and_finished"
17141734
@@ -2250,6 +2270,10 @@ def handshakeServerAsync(self, verifierDB=None,
22502270 for result in self ._handshakeWrapperAsync (handshaker , checker ):
22512271 yield result
22522272
2273+ # Log client random and master secret for version < TLS1.3
2274+ if self .sslkeylogfile and self .version < (3 , 4 ):
2275+ self ._log_session_keys ('CLIENT_RANDOM' , self ._clientRandom , self .session .masterSecret )
2276+
22532277
22542278 def _handshakeServerAsyncHelper (self , verifierDB ,
22552279 cert_chain , privateKey , reqCert ,
@@ -2956,6 +2980,14 @@ def _serverTLS13Handshake(self, settings, clientHello, cipherSuite,
29562980 bytearray (b'c hs traffic' ),
29572981 self ._handshake_hash ,
29582982 prf_name )
2983+
2984+ # TLS1.3 log Client and Server traffic secrets for SSLKEYLOGFILE
2985+ if self .sslkeylogfile :
2986+ self ._log_session_keys ('CLIENT_HANDSHAKE_TRAFFIC_SECRET' ,
2987+ clientHello .random ,
2988+ cl_handshake_traffic_secret )
2989+ self ._log_session_keys ('SERVER_HANDSHAKE_TRAFFIC_SECRET' , clientHello .random , sr_handshake_traffic_secret )
2990+
29592991 self .version = version
29602992 self ._recordLayer .calcTLS1_3PendingState (
29612993 cipherSuite ,
@@ -3222,6 +3254,14 @@ def _serverTLS13Handshake(self, settings, clientHello, cipherSuite,
32223254 self ._handshake_hash ,
32233255 prf_name )
32243256
3257+
3258+ # Now that we have all the TLS1.3 secrets during the handshake, log them if necessary
3259+ if self .sslkeylogfile :
3260+ self ._log_session_keys ('EXPORTER_SECRET' , clientHello .random , exporter_master_secret )
3261+ self ._log_session_keys ('CLIENT_TRAFFIC_SECRET_0' , clientHello .random , cl_app_traffic )
3262+ self ._log_session_keys ('SERVER_TRAFFIC_SECRET_0' , clientHello .random , sr_app_traffic )
3263+
3264+
32253265 # verify Finished of client
32263266 cl_finished_key = HKDF_expand_label (cl_handshake_traffic_secret ,
32273267 b"finished" , b'' ,
@@ -3285,7 +3325,9 @@ def _serverTLS13Handshake(self, settings, clientHello, cipherSuite,
32853325 exporterMasterSecret = exporter_master_secret ,
32863326 resumptionMasterSecret = resumption_master_secret ,
32873327 # NOTE it must be a reference, not a copy
3288- tickets = self .tickets )
3328+ tickets = self .tickets ,
3329+ cl_handshake_traffic_secret = cl_handshake_traffic_secret ,
3330+ sr_handshake_traffic_secret = sr_handshake_traffic_secret )
32893331
32903332 # switch to application_traffic_secret for client packets
32913333 self ._changeReadState ()
@@ -4738,6 +4780,11 @@ def _serverFinished(self, premasterSecret, clientRandom, serverRandom,
47384780 clientRandom , serverRandom ,
47394781 cipherImplementations )
47404782
4783+ #Log client random and master secret if SSLKEYLOGFILE is set
4784+ if self .sslkeylogfile and self .version < (3 , 3 ):
4785+ print ('Logging session keys in serverFinished' )
4786+ self ._log_session_keys ("CLIENT_RANDOM" , clientRandom , masterSecret )
4787+
47414788 #Exchange ChangeCipherSpec and Finished messages
47424789 for result in self ._getFinished (masterSecret ,
47434790 cipherSuite ,
@@ -4934,6 +4981,10 @@ def _calculate_master_secret(self, premaster_secret, cipher_suite,
49344981 output_length = 48 )
49354982 return secret
49364983
4984+ def _log_session_keys (self , secret_label , client_random , secret ):
4985+ with open (self .sslkeylogfile , 'a' ) as ssl_key_log_file :
4986+ ssl_key_log_file .write (f"{ secret_label } { client_random .hex ()} { secret .hex ()} \n " )
4987+
49374988 @staticmethod
49384989 def _pickServerKeyExchangeSig (settings , clientHello , certList = None ,
49394990 private_key = None ,
0 commit comments