Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with TLS 1.3 Session Resumption in PyOpenSSL #1380

Open
Smuul opened this issue Nov 5, 2024 · 2 comments
Open

Issue with TLS 1.3 Session Resumption in PyOpenSSL #1380

Smuul opened this issue Nov 5, 2024 · 2 comments

Comments

@Smuul
Copy link

Smuul commented Nov 5, 2024

Description:

I am encountering an issue when attempting to implement session resumption in TLS 1.3 using PyOpenSSL. I have already tried the implementation suggested in #1291.

Scenario:

Client

self.context = SSL.Context(config.secure_version)
self.context.set_session_cache_mode(SSL.SESS_CACHE_CLIENT)
if session is not None:
             self.conn.set_session(session)

try:
                self.conn.set_connect_state()
                self.conn.do_handshake()
                while self._running:
                    data = self.conn.recv(1)
                    if data:
                            self.session = self.conn.get_session()  
                            break         

Server

self.context = SSL.Context(config.secure_version)
self.context.set_session_cache_mode(SSL.SESS_CACHE_SERVER)
self.context.set_session_id(b'12345678123456781234567812345678')

Observations:

The session resumption works correctly with TLS 1.2:
image

However, the same implementation fails for TLS 1.3. It always creates a new Session Ticket during the second connection attempt:
image

Questions:

What am I doing wrong in my implementation? Is there anything I might be missing to achieve proper session resumption for TLS 1.3?

Any guidance would be greatly appreciated!

@dennisn00
Copy link

In TLS1.3, a server may send a NewSessionTicket even on a resumed connection (for example to extend the lifetime of the original session ticket). I am not sure whether pyOpenSSL is doing that on default, but the existence of a NewSessionTicket message itself should not be proof that the session was not resumed.
You could test manually whether certificates are sent by using set_verify() on the client side:

def test_verification(a, b, c, d, e):
    print("Certificate is verified")
    return True

self.context.set_verify(SSL.VERIFY_PEER, test_verification)

This should only print on the complete handshake (it will print multiple times though) and not during the resuming handshake.

Also just looking at the message sizes in your screenshot, it seems like the second ClientHello is a lot bigger, which might be the PSK. You can check in Wireshark whether the second ClientHello includes the pre_shared_key extension

@Smuul
Copy link
Author

Smuul commented Nov 12, 2024

I finally managed to get the second ClientHello to use the pre_shared_key extension, and the value of the new session ticket issued during the initial handshake. Here’s how I addressed the problem:

Added Sleep Delays: I added some sleep intervals in my code where the client and server instances are created. It seems that allowing a little delay between the different stages helped in stabilizing the session ticket process. Without these sleeps, it appears that the client wasn't ready to properly use the received ticket for resumption.

In addition, i don't use Certificates in my implementation, as i want to use a PSK cipher.
Thanks a lot for your help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants