It's hard to use an alternative TLS API with Curio


#1

I’m experimenting with libtls, an alternative to OpenSSL’s TLS API (it comes from the LibreSSL team and therefore uses OpenSSL code under the covers, but their TLS API is smaller and could change its underlying implementation later). I’ve got a Python binding which seems to work OK with synchronous code as well as asynchronous code (tested using asyncore).

I thought of trying to see if I could use it with Curio: I have a Context object which looks like the stdlib ssl.SSLContext object in that it provides a compatible wrap_socket method, and the wrapped socket has do_handshake, send, recv methods which raise SSLWantReadError and SSLWantWriteError when necessary. However, I’m stymied because Curio has its own SSLContext which wraps the returned socket with a curio.Socket, and if I pass in either my own Context or a bare ssl.SSLContext instance to curio.network.open_connection, I get a failure due to the fact that Curio’s do_handshake returns a value, whereas the ssl.SSLSocket and my own WrappedSocket don’t return a value from their do_handshake.

Another thing is that if I pass in a stdlib ssl.SSLContext instance, the SSLSocket which it returns from wrap_socket is a blocking socket, which needs wrapping in a Curio socket to make it non-blocking and to have an awaitable do_handshake.

Wouldn’t it be better if the Curio socket wrapping happened in curio.network._wrap_ssl_client between the following lines?

    sock = sslcontext.wrap_socket(sock, **extra_args)
    await sock.do_handshake()

Or is there a better approach for what I want to do?


#2

I’m open to all ideas on this. To be honest, the Curio SSL API was minimally copied from the one in the Python standard library just to have something that could work. Refactoring it to make it easier to use something other than the normal SSLContext would probably be a good idea. I’ll look into this.


#3

OK, noted. I’ve got the client-side wrapping sorted out (I think) and am working on the server side wrapping - hopefully not too far off. Will let you know how I get on.

It’s a lot easier to work with Curio than asyncio :smile:


#4

I can report that I’ve managed to get my TLS context working with Curio after making only a small number of changes to the curio.network module. The test program is in this Gist. You can’t usefully run it without the libtls wrapper, which I haven’t yet released.

The changes don’t appear to have caused any regressions. They are in this pull request.

The ssl_echo.py and ssl_echo_client.py programs in the Curio examples directory also work with these changes, after changing to use the stdlib ssl.SSLContext. The modified scripts are in the same Gist as linked above.


#5

Thanks for merging my changes. After doing some more tests, I have found a regression caused by them. I believe I have fixed it, and am adding a test to cover it. I see you might be doing a 0.5 release soon, so I thought I’d better mention it. A PR for the fix and test should be incoming soon.