-
-
Notifications
You must be signed in to change notification settings - Fork 8.6k
Description
Currently MicroPython supports SSL/TLS connections using ussl.wrap_socket(). CPython long ago replaced this function with ssl.SSLContext:
Since Python 3.2 and 2.7.9, it is recommended to use the SSLContext.wrap_socket() of an SSLContext instance to wrap sockets as SSLSocket objects.
And in CPython ssl.wrap_socket() is deprecated since CPython version 3.7.
I propose that MicroPython also switch to using SSLContext. The reasons to change are:
- To more closely match CPython (it's hard to get TLS correct and having things match CPython makes it easier to write tests to compare uPy and CPy).
- To support more sophisticated use of TLS connections (
SSLContextprovide more control/options). - So that
uasynciocan support TLS clients and servers (CPythonasynciorequires passing in anSSLContextobject toasyncio.start_server()andasyncio.open_connection()). - To support
server_hostnamein a CPython-compatible way.
One other benefit of using SSLContext is that it can be used to preallocate the large TLS buffers (16K) needed for a wrapped socket, and the buffer can be reused over and over as long as only one wrapped socket is needed at a time. This will help to reduce memory fragmentation and guarantee that sockets can be wrapped without running out of memory.
The proposed ussl module would now look like this:
# constants
PROTOCOL_TLS_CLIENT
PROTOCOL_TLS_SERVER
class SSLSocket:
# same as existing ssl socket object
class SSLContext:
def __init__(self, protocol):
# protocol is PROTOCOL_TLS_CLIENT or PROTOCOL_TLS_SERVER
def load_cert_chain(self, certfile, keyfile):
# load certificate/key from a file
def wrap_socket(self, sock, *, server_side=False, do_handshake_on_connect=True, server_hostname=None):
# wrap a socket and return an SSLSocket
def wrap_socket(...):
# existing function for backwards compatibilityThings to discuss/decide:
- Should probably keep the existing
ussl.wrap_socket()for backwards compatibility for a couple of releases. It could print a deprecation warning. load_cert_chain()takes filenames as arguments and loads the key/cert from a file. This is different to the existingkey/certargs inussl.wrap_socket()(which are not CPython compatible) that take a str/bytes object containing the key/cert data. The question is if we should add, as a MicroPython-extension, a way to pass in data directly like this, and if yes how that would be done. For example add keyword-only args likeload_cert_chain(self, certfile, keyfile, *, keydata, certdata), or a new method likeload_cert_chain_data(self, keydata, certdata).- Whether to implement it in C or Python.