4343from .utils .cipherfactory import createAESCCM , createAESCCM_8 , \
4444 createAESGCM , createCHACHA20
4545from .utils .compression import choose_compression_send_algo
46+ from .sslkeylogging import SSLKeyLogger
4647
4748
4849class TLSConnection (TLSRecordLayer ):
@@ -80,14 +81,20 @@ class TLSConnection(TLSRecordLayer):
8081 compression wasn't used then it is set to None.
8182 """
8283
83- def __init__ (self , sock ):
84+ def __init__ (self , sock , ssl_key_log_file = None ):
8485 """Create a new TLSConnection instance.
8586
8687 :param sock: The socket data will be transmitted on. The
8788 socket should already be connected. It may be in blocking or
8889 non-blocking mode.
8990
9091 :type sock: socket.socket
92+
93+ :param ssl_key_log_file: override location for logging session secrets.
94+ If not provided the filepath pointed to by the SSLKEYLOGFILE env
95+ variable will be used.
96+
97+ :type ssl_key_log_file: str
9198 """
9299 TLSRecordLayer .__init__ (self , sock )
93100 self .serverSigAlg = None
@@ -105,6 +112,7 @@ def __init__(self, sock):
105112 self ._pha_supported = False
106113 self .client_cert_compression_algo = None
107114 self .server_cert_compression_algo = None
115+ self .ssl_key_logger = SSLKeyLogger (ssl_key_log_file )
108116
109117 def keyingMaterialExporter (self , label , length = 20 ):
110118 """Return keying material as described in RFC 5705
@@ -418,7 +426,6 @@ def _handshakeClientAsync(self, srpParams=(), certParams=(), anonParams=(),
418426 session = None , settings = None , checker = None ,
419427 nextProtos = None , serverName = None , reqTack = True ,
420428 alpn = None ):
421-
422429 handshaker = self ._handshakeClientAsyncHelper (srpParams = srpParams ,
423430 certParams = certParams ,
424431 anonParams = anonParams ,
@@ -431,6 +438,16 @@ def _handshakeClientAsync(self, srpParams=(), certParams=(), anonParams=(),
431438 for result in self ._handshakeWrapperAsync (handshaker , checker ):
432439 yield result
433440
441+ # Log client random and master secret for version < TLS1.3
442+ # in the case of SRP fault, the session instance will be None
443+ if self .session is not None :
444+ if self .version < (3 , 4 ):
445+ self .ssl_key_logger .log_session_keys ([(
446+ 'CLIENT_RANDOM' ,
447+ self ._clientRandom ,
448+ self .session .masterSecret
449+ )])
450+
434451
435452 def _handshakeClientAsyncHelper (self , srpParams , certParams , anonParams ,
436453 session , settings , serverName , nextProtos ,
@@ -1332,6 +1349,14 @@ def _clientTLS13Handshake(self, settings, session, clientHello,
13321349 self ._handshake_hash ,
13331350 prfName )
13341351
1352+ # TLS1.3 log Client and Server traffic secrets for SSLKEYLOGFILE
1353+ self .ssl_key_logger .log_session_keys ([
1354+ ('CLIENT_HANDSHAKE_TRAFFIC_SECRET' ,
1355+ clientHello .random , cl_handshake_traffic_secret ),
1356+ ('SERVER_HANDSHAKE_TRAFFIC_SECRET' ,
1357+ clientHello .random , sr_handshake_traffic_secret )
1358+ ])
1359+
13351360 # prepare for reading encrypted messages
13361361 self ._recordLayer .calcTLS1_3PendingState (
13371362 serverHello .cipher_suite ,
@@ -1656,6 +1681,15 @@ def _clientTLS13Handshake(self, settings, session, clientHello,
16561681 bytearray (b'exp master' ),
16571682 self ._handshake_hash , prfName )
16581683
1684+
1685+ # Now that we have all the TLS1.3 secrets during the handshake,
1686+ # log them if necessary
1687+ self .ssl_key_logger .log_session_keys ([
1688+ ('EXPORTER_SECRET' , clientHello .random , exporter_master_secret ),
1689+ ('CLIENT_TRAFFIC_SECRET_0' , clientHello .random , cl_app_traffic ),
1690+ ('SERVER_TRAFFIC_SECRET_0' , clientHello .random , sr_app_traffic )
1691+ ])
1692+
16591693 self ._recordLayer .calcTLS1_3PendingState (
16601694 serverHello .cipher_suite ,
16611695 cl_app_traffic ,
@@ -1752,7 +1786,9 @@ def _clientTLS13Handshake(self, settings, session, clientHello,
17521786 resumptionMasterSecret = resumption_master_secret ,
17531787 # NOTE it must be a reference, not a copy!
17541788 tickets = self .tickets ,
1755- delegated_credential = delegated_credential )
1789+ delegated_credential = delegated_credential ,
1790+ cl_hs_traffic_secret = cl_handshake_traffic_secret ,
1791+ sr_hs_traffic_secret = sr_handshake_traffic_secret )
17561792
17571793 yield "finished" if not resuming else "resumed_and_finished"
17581794
@@ -2305,6 +2341,16 @@ def handshakeServerAsync(self, verifierDB=None,
23052341 for result in self ._handshakeWrapperAsync (handshaker , checker ):
23062342 yield result
23072343
2344+ # Log client random and master secret for version < TLS1.3
2345+ # in the case of SRP fault, the session instance will be None
2346+ if self .session is not None :
2347+ if self .version < (3 , 4 ):
2348+ self .ssl_key_logger .log_session_keys ([(
2349+ 'CLIENT_RANDOM' ,
2350+ self ._clientRandom ,
2351+ self .session .masterSecret
2352+ )])
2353+
23082354
23092355 def _handshakeServerAsyncHelper (self , verifierDB ,
23102356 cert_chain , privateKey , reqCert ,
@@ -3032,6 +3078,15 @@ def _serverTLS13Handshake(self, settings, clientHello, cipherSuite,
30323078 bytearray (b'c hs traffic' ),
30333079 self ._handshake_hash ,
30343080 prf_name )
3081+
3082+ # TLS1.3 log Client and Server traffic secrets for SSLKEYLOGFILE
3083+ self .ssl_key_logger .log_session_keys ([
3084+ ('CLIENT_HANDSHAKE_TRAFFIC_SECRET' ,
3085+ clientHello .random , cl_handshake_traffic_secret ),
3086+ ('SERVER_HANDSHAKE_TRAFFIC_SECRET' ,
3087+ clientHello .random , sr_handshake_traffic_secret )
3088+ ])
3089+
30353090 self .version = version
30363091 self ._recordLayer .calcTLS1_3PendingState (
30373092 cipherSuite ,
@@ -3310,6 +3365,19 @@ def _serverTLS13Handshake(self, settings, clientHello, cipherSuite,
33103365 self ._handshake_hash ,
33113366 prf_name )
33123367
3368+
3369+ # Now that we have all the TLS1.3 secrets during the handshake,
3370+ # log them if necessary
3371+ self .ssl_key_logger .log_session_keys ([
3372+ ('EXPORTER_SECRET' ,
3373+ clientHello .random , exporter_master_secret ),
3374+ ('CLIENT_TRAFFIC_SECRET_0' ,
3375+ clientHello .random , cl_app_traffic ),
3376+ ('SERVER_TRAFFIC_SECRET_0' ,
3377+ clientHello .random , sr_app_traffic )
3378+ ])
3379+
3380+
33133381 # verify Finished of client
33143382 cl_finished_key = HKDF_expand_label (cl_handshake_traffic_secret ,
33153383 b"finished" , b'' ,
0 commit comments