1818from .utils .compat import *
1919from .utils .cryptomath import *
2020from .utils .codec import Parser
21- from .utils .lists import to_str_delimiter
21+ from .utils .lists import to_str_delimiter , getFirstMatching
2222from .errors import *
2323from .messages import *
2424from .mathtls import *
2727from .defragmenter import Defragmenter
2828from .handshakehashes import HandshakeHashes
2929from .bufferedsocket import BufferedSocket
30+ from .handshakesettings import HandshakeSettings
31+ from .keyexchange import KeyExchange
3032
3133class TLSRecordLayer (object ):
3234 """
@@ -182,6 +184,10 @@ def __init__(self, sock):
182184 self ._buffer_content_type = None
183185 self ._buffer = bytearray ()
184186
187+ # tuple with list of certificates and the private key that will be
188+ # used for post handshake authentication in TLS 1.3
189+ self ._client_keypair = None
190+
185191 @property
186192 def _send_record_limit (self ):
187193 """Maximum size of payload that can be sent."""
@@ -300,8 +306,13 @@ def readAsync(self, max=None, min=1):
300306 if self .version > (3 , 3 ):
301307 allowedTypes = (ContentType .application_data ,
302308 ContentType .handshake )
303- allowedHsTypes = (HandshakeType .new_session_ticket ,
304- HandshakeType .key_update )
309+ if self ._client_keypair :
310+ allowedHsTypes = (HandshakeType .new_session_ticket ,
311+ HandshakeType .key_update ,
312+ HandshakeType .certificate_request )
313+ else :
314+ allowedHsTypes = (HandshakeType .new_session_ticket ,
315+ HandshakeType .key_update )
305316 else :
306317 allowedTypes = ContentType .application_data
307318 allowedHsTypes = None
@@ -316,10 +327,15 @@ def readAsync(self, max=None, min=1):
316327 result .time = time .time ()
317328 self .tickets .append (result )
318329 continue
319- if isinstance (result , KeyUpdate ):
330+ elif isinstance (result , KeyUpdate ):
320331 for result in self ._handle_keyupdate_request (result ):
321332 yield result
322333 continue
334+ elif isinstance (result , CertificateRequest ):
335+ for result in self ._handle_pha (result ):
336+ if result in (0 , 1 ):
337+ yield
338+ continue
323339 applicationData = result
324340 self ._readBuffer += applicationData .write ()
325341 except TLSRemoteAlert as alert :
@@ -611,6 +627,84 @@ def fileno(self):
611627 # Public Functions END
612628 #*********************************************************
613629
630+ def _handle_pha (self , cert_request ):
631+ cert , p_key = self ._client_keypair
632+
633+ handshake_context = self ._first_handshake_hashes .copy ()
634+ handshake_context .update (cert_request .write ())
635+
636+ prf_name = 'sha256'
637+ prf_size = 32
638+ if self .session .cipherSuite in CipherSuite .sha384PrfSuites :
639+ prf_name = 'sha384'
640+ prf_size = 48
641+
642+ msgs = []
643+ msgs .append (Certificate (CertificateType .x509 , self .version )
644+ .create (cert , cert_request .certificate_request_context ))
645+ handshake_context .update (msgs [0 ].write ())
646+ if p_key :
647+ # sign the CertificateVerify only when we have a private key to do
648+ # that
649+ valid_sig_algs = cert_request .supported_signature_algs
650+ if not valid_sig_algs :
651+ for result in self ._sendError (
652+ AlertDescription .missing_extension ,
653+ "No signature algorithms found in CertificateRequest" ):
654+ yield result
655+ avail_sig_algs = self ._sigHashesToList (HandshakeSettings (), p_key ,
656+ cert , version = (3 , 4 ))
657+ sig_scheme = getFirstMatching (avail_sig_algs , valid_sig_algs )
658+ scheme = SignatureScheme .toRepr (sig_scheme )
659+ sig_scheme = getattr (SignatureScheme , scheme )
660+
661+ signature_context = \
662+ KeyExchange .calcVerifyBytes ((3 , 4 ),
663+ handshake_context ,
664+ sig_scheme , None , None , None ,
665+ prf_name , b'client' )
666+
667+ if sig_scheme [1 ] == SignatureAlgorithm .ecdsa :
668+ pad_type = None
669+ hash_name = HashAlgorithm .toRepr (sig_scheme [0 ])
670+ salt_len = None
671+ else :
672+ pad_type = SignatureScheme .getPadding (scheme )
673+ hash_name = SignatureScheme .getHash (scheme )
674+ salt_len = getattr (hashlib , hash_name )().digest_size
675+
676+ signature = p_key .sign (signature_context ,
677+ pad_type ,
678+ hash_name ,
679+ salt_len )
680+ if not p_key .verify (signature , signature_context ,
681+ pad_type ,
682+ hash_name ,
683+ salt_len ):
684+ for result in self ._sendError (
685+ AlertDescription .internal_error ,
686+ "Certificate Verify signature failed" ):
687+ yield result
688+ certificate_verify = CertificateVerify (self .version )
689+ certificate_verify .create (signature , sig_scheme )
690+
691+ msgs .append (certificate_verify )
692+ handshake_context .update (certificate_verify .write ())
693+
694+ finished_key = HKDF_expand_label (self .session .cl_app_secret ,
695+ b"finished" , b"" ,
696+ prf_size , prf_name )
697+ verify_data = secureHMAC (finished_key ,
698+ handshake_context .digest (prf_name ),
699+ prf_name )
700+
701+ finished = Finished ((3 , 4 ), prf_size )
702+ finished .create (verify_data )
703+ msgs .append (finished )
704+
705+ for result in self ._sendMsgs (msgs ):
706+ yield result
707+
614708 def _shutdown (self , resumable ):
615709 self ._recordLayer .shutdown ()
616710 self .version = (0 ,0 )
0 commit comments