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

General Usage #2

Open
ddurham2 opened this issue Aug 29, 2022 · 9 comments
Open

General Usage #2

ddurham2 opened this issue Aug 29, 2022 · 9 comments

Comments

@ddurham2
Copy link

Hey, I came across your post here. I'm also trying to make PSK work generally in python and pskssl2 seems to be the most viable option.

I'm working in the context of asyncio (aiohttp) and so you're post was most helpful.

I believe I have your code working on the aiohttp server side. I can get openssl s_client to have failure/success depending on the chosen PSK, but it isn't helpful to actually make HTTP requests. Unfortunately, curl and wget on the cli don't offer any PSK options.

So I started working with your code on an aiohttp client side to verify. But I'm running into an error

    return await self._loop.create_connection(*args, **kwargs)  # type: ignore[return-value]  # noqa
  File "/usr/lib/python3.8/asyncio/base_events.py", line 1050, in create_connection
    transport, protocol = await self._create_connection_transport(
  File "/usr/lib/python3.8/asyncio/base_events.py", line 1080, in _create_connection_transport
    await waiter
  File "/usr/lib/python3.8/asyncio/sslproto.py", line 529, in data_received
    ssldata, appdata = self._sslpipe.feed_ssldata(data)
  File "/usr/lib/python3.8/asyncio/sslproto.py", line 189, in feed_ssldata
    self._sslobj.do_handshake()
  File "tc.py", line 59, in do_handshake
    super().do_handshake(*args, **kwargs)
  File "/usr/lib/python3.8/ssl.py", line 944, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT] attempt to reuse session in different context (_ssl.c:1131)

This is an error from openssl itself. Something is getting confused I guess and it's thinking I'm trying to resume a session (which a similar operation but not what I'm doing).
I'm simply supplying your subclass of SSLContext to aiohttp.get() which is generally how to customize the ssl context. This could be a problem with how aiohttp is working. But I was wondering if you've run into a similar error.

Thanks (sorry for not-the-best-means of communicating, but I wasn't sure how else to ask).

I'm trying to get something going in the short term, but once I grok this, I may attempt to submit a upstream patch for general PSK support.

@maovidal
Copy link
Owner

Hi @ddurham2
I'm afraid I don't have something that can be useful to help debugging what you are experiencing. I'm still learning about all this.
However I can tell you that I haven't seen that SSLError in any of my tests. My wild guess is that "reuse session" is related to concurrent processes.
I'll keep you posted if I come across something useful.
Thank you for reaching out!

@ddurham2
Copy link
Author

ddurham2 commented Aug 30, 2022

Thanks for the follow up. Unfortunately, no concurrency here in my little example so far. No idea.

Feel free to close this.. or we can keep it open in case one of us finds something.

@ddurham2
Copy link
Author

ddurham2 commented Aug 31, 2022

I think I found your problem.. fixed it for me...

At least when using TLSv1.2 and limited ciphers to PSK on required both side... i.e.
context.options |= ssl.OP_NO_TLSv1_3
context.set_ciphers('PSK')

Your do_handshake overrides need to not call the setup more than once. do_install(), when async of course, is going to get reinvoked for each of the 3 to 4 legs of the SSL handshake.

e.g.

    def do_handshake(self, *args, **kwargs):
        if not hasattr(self, '_did_psk_setup'):
            _ssl_setup_psk_callbacks(self)
            self._did_psk_setup = True
        super().do_handshake(*args, **kwargs)

The actual problem is that your _ssl_setup_psk_callbacks() calls _ssl_set_psk_server_callback() which then calls SSL_set_accept_state() which resets the SSL handshake state. Since these do_handshake() overloads are calling _ssl_setup_psk_callbacks() every time, we'll abort the connection on the second time through do_handshake().

BTW- The hasattr() business has to do with the fact that the init() method of those classes don't get called, so you can't initialize the flag to False.

I'm still digging to try and make it work for TLSv1.3. Enabling 1.3 gives the ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT error on the client side.

@ddurham2
Copy link
Author

ddurham2 commented Aug 31, 2022

Just noting, context.set_ciphers("PSK") seems to be required, because without explictly setting the ciphers, PSK ciphers just aren't in the default list advertised in the client hello message.

I found that set_ciphers('ALL') on the server and set_ciphers('PSK') on the client works. But if you leave either side as the default configured ciphers, then PSK just doesn't work. So it kinda has to be requested explicitly using either ALL or PSK.

@ddurham2
Copy link
Author

ddurham2 commented Aug 31, 2022

When using TLS1.3, I receive the ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT

I get this error using the synchronous wrap_socket() implementation as well as asyncio.

UPDATE:
Accoding to https://docs.python.org/3/library/ssl.html?highlight=set_ciphers#tls-1-3 ...

SSLContext.set_ciphers() cannot be used to control 1.3 ciphers. And when I log what context.get_ciphers() (which does include which 1.3 ciphers are enabled), PSK ciphers are not listed.
Hence, I believe that TLS-PSK doesn't work when 1.3 is left enabled because PSK ciphers are not enabled. It's just that the error code (ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT) is just misleading.

So, until python3 allows calling set_cipher_suites() or something (necessary for 1.3), we're limited to 1.2 with TLS-PSK.

@ddurham2
Copy link
Author

ddurham2 commented Aug 31, 2022

Thanks again for the excellent head start on this. This may give me enough info to submit a PR for python 3.12+, and eventually eliminate the need for sslpsk2.

Let me know if this info helps with your project.

@maovidal
Copy link
Owner

maovidal commented Sep 1, 2022

That is awesome @ddurham2
Thank you for all this information... It's so nice of you to share such detailed findings.
I rushed to test the modified do_handshake per your insights. While it didn't worked in my case as I'm testing the client against another machine whose server is not based on this (the fix that prevents the set_accept_state seems to be related just to the server's do_handshake), your posts have provided me many things to think about.
Thank you again!

@ddurham2
Copy link
Author

ddurham2 commented Sep 1, 2022

That's correct. It's the server that has the problem with the extra initiations of SSL_set_accept_state() ("accepting" a connection is only a server side concern)

Glad to help.

@maovidal
Copy link
Owner

maovidal commented Mar 5, 2023

Hey @ddurham2:

I was revisiting this repo and noticed you proposed some very interesting changes here https://github.com/ddurham2/sslpsk2/tree/add-sslcontext

However it seems you closed them before those were merged. May I ask, if that was for any particular reason?

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

No branches or pull requests

2 participants