4040from .utils .cipherfactory import createAESCCM , createAESCCM_8 , \
4141 createAESGCM , createCHACHA20
4242from .utils .compression import choose_compression_send_algo
43+ from .sslkeylogging import SSLKeyLogger
4344
4445class TLSConnection (TLSRecordLayer ):
4546 """
@@ -76,14 +77,17 @@ class TLSConnection(TLSRecordLayer):
7677 compression wasn't used then it is set to None.
7778 """
7879
79- def __init__ (self , sock ):
80+ def __init__ (self , sock , logging_enabled = False ):
8081 """Create a new TLSConnection instance.
8182
8283 :param sock: The socket data will be transmitted on. The
8384 socket should already be connected. It may be in blocking or
8485 non-blocking mode.
8586
8687 :type sock: socket.socket
88+
89+ :param logging_enabled: Enable logging session secrets to the SSLKEYLOGFILE env variable.
90+ :type logging_enabled: bool
8791 """
8892 TLSRecordLayer .__init__ (self , sock )
8993 self .serverSigAlg = None
@@ -101,6 +105,7 @@ def __init__(self, sock):
101105 self ._pha_supported = False
102106 self .client_cert_compression_algo = None
103107 self .server_cert_compression_algo = None
108+ self .ssl_key_logger = SSLKeyLogger (logging_enabled )
104109
105110 def keyingMaterialExporter (self , label , length = 20 ):
106111 """Return keying material as described in RFC 5705
@@ -414,7 +419,6 @@ def _handshakeClientAsync(self, srpParams=(), certParams=(), anonParams=(),
414419 session = None , settings = None , checker = None ,
415420 nextProtos = None , serverName = None , reqTack = True ,
416421 alpn = None ):
417-
418422 handshaker = self ._handshakeClientAsyncHelper (srpParams = srpParams ,
419423 certParams = certParams ,
420424 anonParams = anonParams ,
@@ -427,6 +431,10 @@ def _handshakeClientAsync(self, srpParams=(), certParams=(), anonParams=(),
427431 for result in self ._handshakeWrapperAsync (handshaker , checker ):
428432 yield result
429433
434+ # Log client random and master secret for version < TLS1.3
435+ if self .version < (3 , 4 ):
436+ self .ssl_key_logger .log_session_keys (('CLIENT_RANDOM' , self ._clientRandom , self .session .masterSecret ))
437+
430438
431439 def _handshakeClientAsyncHelper (self , srpParams , certParams , anonParams ,
432440 session , settings , serverName , nextProtos ,
@@ -1323,6 +1331,14 @@ def _clientTLS13Handshake(self, settings, session, clientHello,
13231331 self ._handshake_hash ,
13241332 prfName )
13251333
1334+ # TLS1.3 log Client and Server traffic secrets for SSLKEYLOGFILE
1335+ self .ssl_key_logger .log_session_keys ([
1336+ ('CLIENT_HANDSHAKE_TRAFFIC_SECRET' ,
1337+ clientHello .random , cl_handshake_traffic_secret ),
1338+ ('SERVER_HANDSHAKE_TRAFFIC_SECRET' ,
1339+ clientHello .random , sr_handshake_traffic_secret )
1340+ ])
1341+
13261342 # prepare for reading encrypted messages
13271343 self ._recordLayer .calcTLS1_3PendingState (
13281344 serverHello .cipher_suite ,
@@ -1613,6 +1629,15 @@ def _clientTLS13Handshake(self, settings, session, clientHello,
16131629 bytearray (b'exp master' ),
16141630 self ._handshake_hash , prfName )
16151631
1632+
1633+ # Now that we have all the TLS1.3 secrets during the handshake,
1634+ # log them if necessary
1635+ self .ssl_key_logger .log_session_keys ([
1636+ ('EXPORTER_SECRET' , clientHello .random , exporter_master_secret ),
1637+ ('CLIENT_TRAFFIC_SECRET_0' , clientHello .random , cl_app_traffic ),
1638+ ('SERVER_TRAFFIC_SECRET_0' , clientHello .random , sr_app_traffic )
1639+ ])
1640+
16161641 self ._recordLayer .calcTLS1_3PendingState (
16171642 serverHello .cipher_suite ,
16181643 cl_app_traffic ,
@@ -1708,7 +1733,9 @@ def _clientTLS13Handshake(self, settings, session, clientHello,
17081733 exporterMasterSecret = exporter_master_secret ,
17091734 resumptionMasterSecret = resumption_master_secret ,
17101735 # NOTE it must be a reference, not a copy!
1711- tickets = self .tickets )
1736+ tickets = self .tickets ,
1737+ cl_hs_traffic_secret = cl_handshake_traffic_secret ,
1738+ sr_hs_traffic_secret = sr_handshake_traffic_secret )
17121739
17131740 yield "finished" if not resuming else "resumed_and_finished"
17141741
@@ -2250,6 +2277,12 @@ def handshakeServerAsync(self, verifierDB=None,
22502277 for result in self ._handshakeWrapperAsync (handshaker , checker ):
22512278 yield result
22522279
2280+ # Log client random and master secret for version < TLS1.3
2281+ if self .version < (3 , 4 ):
2282+ self .ssl_key_logger .log_session_keys (('CLIENT_RANDOM' ,
2283+ self ._clientRandom ,
2284+ self .session .masterSecret ))
2285+
22532286
22542287 def _handshakeServerAsyncHelper (self , verifierDB ,
22552288 cert_chain , privateKey , reqCert ,
@@ -2956,6 +2989,15 @@ def _serverTLS13Handshake(self, settings, clientHello, cipherSuite,
29562989 bytearray (b'c hs traffic' ),
29572990 self ._handshake_hash ,
29582991 prf_name )
2992+
2993+ # TLS1.3 log Client and Server traffic secrets for SSLKEYLOGFILE
2994+ self .ssl_key_logger .log_session_keys ([
2995+ ('CLIENT_HANDSHAKE_TRAFFIC_SECRET' ,
2996+ clientHello .random , cl_handshake_traffic_secret ),
2997+ ('SERVER_HANDSHAKE_TRAFFIC_SECRET' ,
2998+ clientHello .random , sr_handshake_traffic_secret )
2999+ ])
3000+
29593001 self .version = version
29603002 self ._recordLayer .calcTLS1_3PendingState (
29613003 cipherSuite ,
@@ -3222,6 +3264,19 @@ def _serverTLS13Handshake(self, settings, clientHello, cipherSuite,
32223264 self ._handshake_hash ,
32233265 prf_name )
32243266
3267+
3268+ # Now that we have all the TLS1.3 secrets during the handshake,
3269+ # log them if necessary
3270+ self .ssl_key_logger .log_session_keys ([
3271+ ('EXPORTER_SECRET' ,
3272+ clientHello .random , exporter_master_secret ),
3273+ ('CLIENT_TRAFFIC_SECRET_0' ,
3274+ clientHello .random , cl_app_traffic ),
3275+ ('SERVER_TRAFFIC_SECRET_0' ,
3276+ clientHello .random , sr_app_traffic )
3277+ ])
3278+
3279+
32253280 # verify Finished of client
32263281 cl_finished_key = HKDF_expand_label (cl_handshake_traffic_secret ,
32273282 b"finished" , b'' ,
@@ -3285,7 +3340,9 @@ def _serverTLS13Handshake(self, settings, clientHello, cipherSuite,
32853340 exporterMasterSecret = exporter_master_secret ,
32863341 resumptionMasterSecret = resumption_master_secret ,
32873342 # NOTE it must be a reference, not a copy
3288- tickets = self .tickets )
3343+ tickets = self .tickets ,
3344+ cl_hs_traffic_secret = cl_handshake_traffic_secret ,
3345+ sr_hs_traffic_secret = sr_handshake_traffic_secret )
32893346
32903347 # switch to application_traffic_secret for client packets
32913348 self ._changeReadState ()
@@ -4934,6 +4991,7 @@ def _calculate_master_secret(self, premaster_secret, cipher_suite,
49344991 output_length = 48 )
49354992 return secret
49364993
4994+
49374995 @staticmethod
49384996 def _pickServerKeyExchangeSig (settings , clientHello , certList = None ,
49394997 private_key = None ,
0 commit comments