Skip to content

Commit 35d41db

Browse files
felixdoerredpgeorge
authored andcommitted
ssl: Restructure micropython SSL interface to a new tls module.
MicroPython now supplies SSL/TLS functionality in a new built-in `tls` module. The `ssl` module is now implemented purely in Python, in this repository. Other libraries are updated to work with this scheme. Signed-off-by: Felix Dörre <[email protected]>
1 parent 803452a commit 35d41db

File tree

9 files changed

+81
-44
lines changed

9 files changed

+81
-44
lines changed

Diff for: micropython/bundles/bundle-networking/manifest.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
metadata(
2-
version="0.1.0",
2+
version="0.2.0",
33
description="Common networking packages for all network-capable deployments of MicroPython.",
44
)
55

66
require("mip")
77
require("ntptime")
8+
require("ssl")
89
require("requests")
910
require("webrepl")
1011

Diff for: micropython/umqtt.simple/manifest.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
metadata(description="Lightweight MQTT client for MicroPython.", version="1.3.4")
1+
metadata(description="Lightweight MQTT client for MicroPython.", version="1.4.0")
22

33
# Originally written by Paul Sokolovsky.
44

Diff for: micropython/umqtt.simple/umqtt/simple.py

+2-6
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ def __init__(
1616
user=None,
1717
password=None,
1818
keepalive=0,
19-
ssl=False,
20-
ssl_params={},
19+
ssl=None,
2120
):
2221
if port == 0:
2322
port = 8883 if ssl else 1883
@@ -26,7 +25,6 @@ def __init__(
2625
self.server = server
2726
self.port = port
2827
self.ssl = ssl
29-
self.ssl_params = ssl_params
3028
self.pid = 0
3129
self.cb = None
3230
self.user = user
@@ -67,9 +65,7 @@ def connect(self, clean_session=True):
6765
addr = socket.getaddrinfo(self.server, self.port)[0][-1]
6866
self.sock.connect(addr)
6967
if self.ssl:
70-
import ussl
71-
72-
self.sock = ussl.wrap_socket(self.sock, **self.ssl_params)
68+
self.sock = self.ssl.wrap_socket(self.sock, server_hostname=self.server)
7369
premsg = bytearray(b"\x10\0\0\0\0\0")
7470
msg = bytearray(b"\x04MQTT\x04\x02\0\0")
7571

Diff for: micropython/urllib.urequest/manifest.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
metadata(version="0.6.0")
1+
metadata(version="0.7.0")
22

33
# Originally written by Paul Sokolovsky.
44

Diff for: micropython/urllib.urequest/urllib/urequest.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def urlopen(url, data=None, method="GET"):
1212
if proto == "http:":
1313
port = 80
1414
elif proto == "https:":
15-
import ussl
15+
import tls
1616

1717
port = 443
1818
else:
@@ -29,7 +29,9 @@ def urlopen(url, data=None, method="GET"):
2929
try:
3030
s.connect(ai[-1])
3131
if proto == "https:":
32-
s = ussl.wrap_socket(s, server_hostname=host)
32+
context = tls.SSLContext(tls.PROTOCOL_TLS_CLIENT)
33+
context.verify_mode = tls.CERT_NONE
34+
s = context.wrap_socket(s, server_hostname=host)
3335

3436
s.write(method)
3537
s.write(b" /")

Diff for: python-ecosys/requests/manifest.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
metadata(version="0.8.1", pypi="requests")
1+
metadata(version="0.9.0", pypi="requests")
22

33
package("requests")

Diff for: python-ecosys/requests/requests/__init__.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def request(
6363
if proto == "http:":
6464
port = 80
6565
elif proto == "https:":
66-
import ussl
66+
import tls
6767

6868
port = 443
6969
else:
@@ -90,7 +90,9 @@ def request(
9090
try:
9191
s.connect(ai[-1])
9292
if proto == "https:":
93-
s = ussl.wrap_socket(s, server_hostname=host)
93+
context = tls.SSLContext(tls.PROTOCOL_TLS_CLIENT)
94+
context.verify_mode = tls.CERT_NONE
95+
s = context.wrap_socket(s, server_hostname=host)
9496
s.write(b"%s /%s HTTP/1.0\r\n" % (method, path))
9597
if "Host" not in headers:
9698
s.write(b"Host: %s\r\n" % host)

Diff for: python-stdlib/ssl/manifest.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
metadata(version="0.1.0")
1+
metadata(version="0.2.0")
22

3-
module("ssl.py")
3+
module("ssl.py", opt=3)

Diff for: python-stdlib/ssl/ssl.py

+64-28
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,72 @@
1-
from ussl import *
2-
import ussl as _ussl
1+
import tls
2+
from tls import (
3+
CERT_NONE,
4+
CERT_OPTIONAL,
5+
CERT_REQUIRED,
6+
MBEDTLS_VERSION,
7+
PROTOCOL_TLS_CLIENT,
8+
PROTOCOL_TLS_SERVER,
9+
)
310

4-
# Constants
5-
for sym in "CERT_NONE", "CERT_OPTIONAL", "CERT_REQUIRED":
6-
if sym not in globals():
7-
globals()[sym] = object()
11+
12+
class SSLContext:
13+
def __init__(self, *args):
14+
self._context = tls.SSLContext(*args)
15+
self._context.verify_mode = CERT_NONE
16+
17+
@property
18+
def verify_mode(self):
19+
return self._context.verify_mode
20+
21+
@verify_mode.setter
22+
def verify_mode(self, val):
23+
self._context.verify_mode = val
24+
25+
def load_cert_chain(self, certfile, keyfile):
26+
if isinstance(certfile, str):
27+
with open(certfile, "rb") as f:
28+
certfile = f.read()
29+
if isinstance(keyfile, str):
30+
with open(keyfile, "rb") as f:
31+
keyfile = f.read()
32+
self._context.load_cert_chain(certfile, keyfile)
33+
34+
def load_verify_locations(self, cafile=None, cadata=None):
35+
if cafile:
36+
with open(cafile, "rb") as f:
37+
cadata = f.read()
38+
self._context.load_verify_locations(cadata)
39+
40+
def wrap_socket(
41+
self, sock, server_side=False, do_handshake_on_connect=True, server_hostname=None
42+
):
43+
return self._context.wrap_socket(
44+
sock,
45+
server_side=server_side,
46+
do_handshake_on_connect=do_handshake_on_connect,
47+
server_hostname=server_hostname,
48+
)
849

950

1051
def wrap_socket(
1152
sock,
12-
keyfile=None,
13-
certfile=None,
1453
server_side=False,
54+
key=None,
55+
cert=None,
1556
cert_reqs=CERT_NONE,
16-
*,
17-
ca_certs=None,
18-
server_hostname=None
57+
cadata=None,
58+
server_hostname=None,
59+
do_handshake=True,
1960
):
20-
# TODO: More arguments accepted by CPython could also be handled here.
21-
# That would allow us to accept ca_certs as a positional argument, which
22-
# we should.
23-
kw = {}
24-
if keyfile is not None:
25-
kw["keyfile"] = keyfile
26-
if certfile is not None:
27-
kw["certfile"] = certfile
28-
if server_side is not False:
29-
kw["server_side"] = server_side
30-
if cert_reqs is not CERT_NONE:
31-
kw["cert_reqs"] = cert_reqs
32-
if ca_certs is not None:
33-
kw["ca_certs"] = ca_certs
34-
if server_hostname is not None:
35-
kw["server_hostname"] = server_hostname
36-
return _ussl.wrap_socket(sock, **kw)
61+
con = SSLContext(PROTOCOL_TLS_SERVER if server_side else PROTOCOL_TLS_CLIENT)
62+
if cert or key:
63+
con.load_cert_chain(cert, key)
64+
if cadata:
65+
con.load_verify_locations(cadata=cadata)
66+
con.verify_mode = cert_reqs
67+
return con.wrap_socket(
68+
sock,
69+
server_side=server_side,
70+
do_handshake_on_connect=do_handshake,
71+
server_hostname=server_hostname,
72+
)

0 commit comments

Comments
 (0)