@@ -475,7 +475,7 @@ def test_wrap_buffers(self, context):
475475 assert isinstance (context .wrap_buffers (), TLSWrappedBuffer )
476476
477477
478- class TestTLSWrappedBuffer :
478+ class TestTLSHandshake :
479479 @pytest .fixture
480480 def server_hostname (self ):
481481 return "hostname"
@@ -497,7 +497,7 @@ def srv_conf(self, psk):
497497 )
498498
499499 @pytest .fixture
500- def client (Self , cli_conf , server_hostname ):
500+ def client (self , cli_conf , server_hostname ):
501501 buf = ClientContext (cli_conf ).wrap_buffers (server_hostname )
502502 yield buf
503503 buf .shutdown ()
@@ -587,3 +587,139 @@ def do_handshake(end, states):
587587 amt = server .write (secret )
588588 do_io (src = server , dst = client )
589589 assert client .read (amt ) == secret
590+
591+
592+ class TestDTLSHandshake :
593+ @pytest .fixture
594+ def server_hostname (self ):
595+ return "hostname"
596+
597+ @pytest .fixture
598+ def psk (self ):
599+ return ("cli" , b"secret" )
600+
601+ @pytest .fixture
602+ def cli_conf (self , psk ):
603+ return DTLSConfiguration (
604+ pre_shared_key = psk , validate_certificates = False
605+ )
606+
607+ @pytest .fixture
608+ def srv_conf (self , psk ):
609+ return DTLSConfiguration (
610+ pre_shared_key_store = dict ((psk ,)), validate_certificates = False
611+ )
612+
613+ @pytest .fixture
614+ def client (self , cli_conf , server_hostname ):
615+ buf = ClientContext (cli_conf ).wrap_buffers (server_hostname )
616+ yield buf
617+ buf .shutdown ()
618+
619+ @pytest .fixture
620+ def server (sefl , srv_conf ):
621+ buf = ServerContext (srv_conf ).wrap_buffers ()
622+ yield buf
623+ buf .shutdown ()
624+
625+ @pytest .fixture
626+ def cli_ctx (Self , cli_conf ):
627+ return ClientContext (cli_conf )
628+
629+ @pytest .fixture
630+ def srv_ctx (self , srv_conf ):
631+ return ServerContext (srv_conf )
632+
633+ def test_e2e_handshake_and_communicate (self , client , server ):
634+ def do_io (* , src , dst , amt = 1024 ):
635+ in_transit = src .peek_outgoing (amt )
636+ src .consume_outgoing (len (in_transit ))
637+ dst .receive_from_network (in_transit )
638+
639+ def do_handshake (end , states ):
640+ while end ._handshake_state is not states [0 ]:
641+ # The backend goes through every state for both
642+ # ends. This is not relevant.
643+ end .do_handshake ()
644+
645+ for state in states :
646+ assert end ._handshake_state is state
647+ if state is HandshakeStep .HANDSHAKE_OVER :
648+ break
649+ with suppress (WantReadError , WantWriteError ):
650+ end .do_handshake ()
651+
652+ do_handshake (
653+ client ,
654+ (
655+ HandshakeStep .HELLO_REQUEST ,
656+ HandshakeStep .CLIENT_HELLO ,
657+ ),
658+ )
659+
660+ do_io (src = client , dst = server )
661+ server .setcookieparam ("🍪🍪🍪" .encode ("utf-8" ))
662+ with pytest .raises (HelloVerifyRequest ):
663+ do_handshake (
664+ server ,
665+ (
666+ HandshakeStep .SERVER_HELLO ,
667+ HandshakeStep .SERVER_HELLO_VERIFY_REQUEST_SENT ,
668+ ),
669+ )
670+
671+ do_handshake (server , (HandshakeStep .HELLO_REQUEST ,))
672+ do_io (src = server , dst = client )
673+ do_handshake (client , (HandshakeStep .CLIENT_HELLO ,))
674+ do_io (src = client , dst = server )
675+ server .setcookieparam ("🍪🍪🍪" .encode ("utf-8" ))
676+ do_handshake (
677+ server ,
678+ (
679+ HandshakeStep .SERVER_HELLO ,
680+ HandshakeStep .SERVER_CERTIFICATE ,
681+ HandshakeStep .SERVER_KEY_EXCHANGE ,
682+ HandshakeStep .CERTIFICATE_REQUEST ,
683+ HandshakeStep .SERVER_HELLO_DONE ,
684+ ),
685+ )
686+ assert client .negotiated_protocol () == server .negotiated_protocol ()
687+
688+ do_io (src = server , dst = client )
689+ do_handshake (
690+ client ,
691+ (
692+ HandshakeStep .CLIENT_KEY_EXCHANGE ,
693+ HandshakeStep .CERTIFICATE_VERIFY ,
694+ HandshakeStep .CLIENT_CHANGE_CIPHER_SPEC ,
695+ HandshakeStep .CLIENT_FINISHED ,
696+ ),
697+ )
698+ assert (
699+ client .negotiated_tls_version () == server .negotiated_tls_version ()
700+ )
701+
702+ do_io (src = client , dst = server )
703+ do_handshake (
704+ server ,
705+ (
706+ HandshakeStep .SERVER_CHANGE_CIPHER_SPEC ,
707+ HandshakeStep .SERVER_FINISHED ,
708+ HandshakeStep .FLUSH_BUFFERS ,
709+ HandshakeStep .HANDSHAKE_WRAPUP ,
710+ HandshakeStep .HANDSHAKE_OVER ,
711+ ),
712+ )
713+ do_io (src = server , dst = client )
714+ do_handshake (client , (HandshakeStep .HANDSHAKE_OVER ,))
715+ assert client .cipher () == server .cipher ()
716+
717+ secret = b"a very secret message"
718+
719+ amt = client .write (secret )
720+ do_io (src = client , dst = server )
721+ assert server .read (amt ) == secret
722+
723+ amt = server .write (secret )
724+ do_io (src = server , dst = client )
725+ assert client .read (amt ) == secret
0 commit comments