-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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 (
SSLContext
provide more control/options). - So that
uasyncio
can support TLS clients and servers (CPythonasyncio
requires passing in anSSLContext
object toasyncio.start_server()
andasyncio.open_connection()
). - To support
server_hostname
in 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 compatibility
Things 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
/cert
args 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.