mirror of
https://github.com/licsber/micropython.git
synced 2024-09-20 00:50:24 +08:00
extmod/modtls: Move the native ssl module to tls.
The current `ssl` module has quite a few differences to the CPython implementation. This change moves the MicroPython variant to a new `tls` module and provides a wrapper module for `ssl` (in micropython-lib). Users who only rely on implemented comparible behavior can continue to use `ssl`, while users that rely on non-compatible behavior should switch to `tls`. Then we can make the facade in `ssl` more strictly adhere to CPython. Signed-off-by: Felix Dörre <felix@dogcraft.de>
This commit is contained in:
parent
f8f1f29ac0
commit
b802f0f8ab
@ -39,8 +39,8 @@ set(MICROPY_SOURCE_EXTMOD
|
||||
${MICROPY_EXTMOD_DIR}/modre.c
|
||||
${MICROPY_EXTMOD_DIR}/modselect.c
|
||||
${MICROPY_EXTMOD_DIR}/modsocket.c
|
||||
${MICROPY_EXTMOD_DIR}/modssl_axtls.c
|
||||
${MICROPY_EXTMOD_DIR}/modssl_mbedtls.c
|
||||
${MICROPY_EXTMOD_DIR}/modtls_axtls.c
|
||||
${MICROPY_EXTMOD_DIR}/modtls_mbedtls.c
|
||||
${MICROPY_EXTMOD_DIR}/modtime.c
|
||||
${MICROPY_EXTMOD_DIR}/modwebsocket.c
|
||||
${MICROPY_EXTMOD_DIR}/modwebrepl.c
|
||||
|
@ -36,8 +36,8 @@ SRC_EXTMOD_C += \
|
||||
extmod/modre.c \
|
||||
extmod/modselect.c \
|
||||
extmod/modsocket.c \
|
||||
extmod/modssl_axtls.c \
|
||||
extmod/modssl_mbedtls.c \
|
||||
extmod/modtls_axtls.c \
|
||||
extmod/modtls_mbedtls.c \
|
||||
extmod/modtime.c \
|
||||
extmod/moductypes.c \
|
||||
extmod/modwebrepl.c \
|
||||
|
@ -422,48 +422,8 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE(
|
||||
/******************************************************************************/
|
||||
// ssl module.
|
||||
|
||||
STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum {
|
||||
ARG_key,
|
||||
ARG_cert,
|
||||
ARG_server_side,
|
||||
ARG_server_hostname,
|
||||
ARG_do_handshake,
|
||||
};
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||
{ MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||
{ MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
|
||||
{ MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||
{ MP_QSTR_do_handshake, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
|
||||
};
|
||||
|
||||
// Parse arguments.
|
||||
mp_obj_t sock = pos_args[0];
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
// Create SSLContext.
|
||||
mp_int_t protocol = args[ARG_server_side].u_bool ? PROTOCOL_TLS_SERVER : PROTOCOL_TLS_CLIENT;
|
||||
mp_obj_t ssl_context_args[1] = { MP_OBJ_NEW_SMALL_INT(protocol) };
|
||||
mp_obj_ssl_context_t *ssl_context = MP_OBJ_TO_PTR(ssl_context_make_new(&ssl_context_type, 1, 0, ssl_context_args));
|
||||
|
||||
// Load key and cert if given.
|
||||
if (args[ARG_key].u_obj != mp_const_none) {
|
||||
ssl_context_load_key(ssl_context, args[ARG_key].u_obj, args[ARG_cert].u_obj);
|
||||
}
|
||||
|
||||
// Create and return the new SSLSocket object.
|
||||
return ssl_socket_make_new(ssl_context, sock, args[ARG_server_side].u_bool,
|
||||
args[ARG_do_handshake].u_bool, args[ARG_server_hostname].u_obj);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socket);
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ssl) },
|
||||
|
||||
// Functions.
|
||||
{ MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&mod_ssl_wrap_socket_obj) },
|
||||
STATIC const mp_rom_map_elem_t mp_module_tls_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_tls) },
|
||||
|
||||
// Classes.
|
||||
{ MP_ROM_QSTR(MP_QSTR_SSLContext), MP_ROM_PTR(&ssl_context_type) },
|
||||
@ -472,13 +432,13 @@ STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLS_CLIENT), MP_ROM_INT(PROTOCOL_TLS_CLIENT) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLS_SERVER), MP_ROM_INT(PROTOCOL_TLS_SERVER) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_ssl_globals, mp_module_ssl_globals_table);
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_tls_globals, mp_module_tls_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_ssl = {
|
||||
const mp_obj_module_t mp_module_tls = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&mp_module_ssl_globals,
|
||||
.globals = (mp_obj_dict_t *)&mp_module_tls_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_ssl, mp_module_ssl);
|
||||
MP_REGISTER_MODULE(MP_QSTR_tls, mp_module_tls);
|
||||
|
||||
#endif // MICROPY_PY_SSL && MICROPY_SSL_AXTLS
|
@ -91,24 +91,6 @@ STATIC mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t
|
||||
/******************************************************************************/
|
||||
// Helper functions.
|
||||
|
||||
STATIC mp_obj_t read_file(mp_obj_t self_in) {
|
||||
// file = open(args[0], "rb")
|
||||
mp_obj_t f_args[2] = {
|
||||
self_in,
|
||||
MP_OBJ_NEW_QSTR(MP_QSTR_rb),
|
||||
};
|
||||
mp_obj_t file = mp_vfs_open(2, &f_args[0], (mp_map_t *)&mp_const_empty_map);
|
||||
|
||||
// data = file.read()
|
||||
mp_obj_t dest[2];
|
||||
mp_load_method(file, MP_QSTR_read, dest);
|
||||
mp_obj_t data = mp_call_method_n_kw(0, 0, dest);
|
||||
|
||||
// file.close()
|
||||
mp_stream_close(file);
|
||||
return data;
|
||||
}
|
||||
|
||||
#ifdef MBEDTLS_DEBUG_C
|
||||
STATIC void mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str) {
|
||||
(void)ctx;
|
||||
@ -256,9 +238,7 @@ STATIC mp_obj_t ssl_context_make_new(const mp_obj_type_t *type_in, size_t n_args
|
||||
}
|
||||
|
||||
if (endpoint == MBEDTLS_SSL_IS_CLIENT) {
|
||||
// The CPython default is MBEDTLS_SSL_VERIFY_REQUIRED, but to maintain
|
||||
// backwards compatibility we use MBEDTLS_SSL_VERIFY_NONE for now.
|
||||
self->authmode = MBEDTLS_SSL_VERIFY_NONE;
|
||||
self->authmode = MBEDTLS_SSL_VERIFY_REQUIRED;
|
||||
} else {
|
||||
self->authmode = MBEDTLS_SSL_VERIFY_NONE;
|
||||
}
|
||||
@ -376,25 +356,9 @@ STATIC void ssl_context_load_key(mp_obj_ssl_context_t *self, mp_obj_t key_obj, m
|
||||
}
|
||||
|
||||
// SSLContext.load_cert_chain(certfile, keyfile)
|
||||
STATIC mp_obj_t ssl_context_load_cert_chain(mp_obj_t self_in, mp_obj_t certfile, mp_obj_t keyfile) {
|
||||
STATIC mp_obj_t ssl_context_load_cert_chain(mp_obj_t self_in, mp_obj_t cert, mp_obj_t pkey) {
|
||||
mp_obj_ssl_context_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_obj_t pkey;
|
||||
mp_obj_t cert;
|
||||
if (certfile != mp_const_none) {
|
||||
// check if key is a string/path
|
||||
if (!(mp_obj_is_type(keyfile, &mp_type_bytes))) {
|
||||
pkey = read_file(keyfile);
|
||||
} else {
|
||||
pkey = keyfile;
|
||||
}
|
||||
// check if cert is a string/path
|
||||
if (!(mp_obj_is_type(certfile, &mp_type_bytes))) {
|
||||
cert = read_file(certfile);
|
||||
} else {
|
||||
cert = certfile;
|
||||
}
|
||||
ssl_context_load_key(self, pkey, cert);
|
||||
}
|
||||
ssl_context_load_key(self, pkey, cert);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(ssl_context_load_cert_chain_obj, ssl_context_load_cert_chain);
|
||||
@ -411,29 +375,14 @@ STATIC void ssl_context_load_cadata(mp_obj_ssl_context_t *self, mp_obj_t cadata_
|
||||
mbedtls_ssl_conf_ca_chain(&self->conf, &self->cacert, NULL);
|
||||
}
|
||||
|
||||
// SSLContext.load_verify_locations(cafile=None, *, cadata=None)
|
||||
STATIC mp_obj_t ssl_context_load_verify_locations(size_t n_args, const mp_obj_t *pos_args,
|
||||
mp_map_t *kw_args) {
|
||||
// SSLContext.load_verify_locations(cadata)
|
||||
STATIC mp_obj_t ssl_context_load_verify_locations(mp_obj_t self_in, mp_obj_t cadata) {
|
||||
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_cafile, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||
{ MP_QSTR_cadata, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||
};
|
||||
|
||||
mp_obj_ssl_context_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
// cafile
|
||||
if (args[0].u_obj != mp_const_none) {
|
||||
ssl_context_load_cadata(self, read_file(args[0].u_obj));
|
||||
}
|
||||
// cadata
|
||||
if (args[1].u_obj != mp_const_none) {
|
||||
ssl_context_load_cadata(self, args[1].u_obj);
|
||||
}
|
||||
mp_obj_ssl_context_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
ssl_context_load_cadata(self, cadata);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(ssl_context_load_verify_locations_obj, 1, ssl_context_load_verify_locations);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(ssl_context_load_verify_locations_obj, ssl_context_load_verify_locations);
|
||||
|
||||
STATIC mp_obj_t ssl_context_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_server_side, ARG_do_handshake_on_connect, ARG_server_hostname };
|
||||
@ -788,61 +737,8 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE(
|
||||
/******************************************************************************/
|
||||
// ssl module.
|
||||
|
||||
STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum {
|
||||
ARG_key,
|
||||
ARG_cert,
|
||||
ARG_server_side,
|
||||
ARG_server_hostname,
|
||||
ARG_cert_reqs,
|
||||
ARG_cadata,
|
||||
ARG_do_handshake,
|
||||
};
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||
{ MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||
{ MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
|
||||
{ MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||
{ MP_QSTR_cert_reqs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = MBEDTLS_SSL_VERIFY_NONE}},
|
||||
{ MP_QSTR_cadata, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||
{ MP_QSTR_do_handshake, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
|
||||
};
|
||||
|
||||
// Parse arguments.
|
||||
mp_obj_t sock = pos_args[0];
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
// Create SSLContext.
|
||||
mp_int_t protocol = args[ARG_server_side].u_bool ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT;
|
||||
mp_obj_t ssl_context_args[1] = { MP_OBJ_NEW_SMALL_INT(protocol) };
|
||||
mp_obj_ssl_context_t *ssl_context = MP_OBJ_TO_PTR(ssl_context_make_new(&ssl_context_type, 1, 0, ssl_context_args));
|
||||
|
||||
// Load key and cert if given.
|
||||
if (args[ARG_key].u_obj != mp_const_none) {
|
||||
ssl_context_load_key(ssl_context, args[ARG_key].u_obj, args[ARG_cert].u_obj);
|
||||
}
|
||||
|
||||
// Set the verify_mode.
|
||||
mp_obj_t dest[2] = { MP_OBJ_SENTINEL, MP_OBJ_NEW_SMALL_INT(args[ARG_cert_reqs].u_int) };
|
||||
ssl_context_attr(MP_OBJ_FROM_PTR(ssl_context), MP_QSTR_verify_mode, dest);
|
||||
|
||||
// Load cadata if given.
|
||||
if (args[ARG_cadata].u_obj != mp_const_none) {
|
||||
ssl_context_load_cadata(ssl_context, args[ARG_cadata].u_obj);
|
||||
}
|
||||
|
||||
// Create and return the new SSLSocket object.
|
||||
return ssl_socket_make_new(ssl_context, sock, args[ARG_server_side].u_bool,
|
||||
args[ARG_do_handshake].u_bool, args[ARG_server_hostname].u_obj);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socket);
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ssl) },
|
||||
|
||||
// Functions.
|
||||
{ MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&mod_ssl_wrap_socket_obj) },
|
||||
STATIC const mp_rom_map_elem_t mp_module_tls_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_tls) },
|
||||
|
||||
// Classes.
|
||||
{ MP_ROM_QSTR(MP_QSTR_SSLContext), MP_ROM_PTR(&ssl_context_type) },
|
||||
@ -855,13 +751,13 @@ STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_CERT_OPTIONAL), MP_ROM_INT(MBEDTLS_SSL_VERIFY_OPTIONAL) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_CERT_REQUIRED), MP_ROM_INT(MBEDTLS_SSL_VERIFY_REQUIRED) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_ssl_globals, mp_module_ssl_globals_table);
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_tls_globals, mp_module_tls_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_ssl = {
|
||||
const mp_obj_module_t mp_module_tls = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&mp_module_ssl_globals,
|
||||
.globals = (mp_obj_dict_t *)&mp_module_tls_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_ssl, mp_module_ssl);
|
||||
MP_REGISTER_MODULE(MP_QSTR_tls, mp_module_tls);
|
||||
|
||||
#endif // MICROPY_PY_SSL && MICROPY_SSL_MBEDTLS
|
@ -1,3 +1,4 @@
|
||||
freeze_as_str("frzstr")
|
||||
freeze_as_mpy("frzmpy")
|
||||
freeze_mpy("$(MPY_DIR)/tests/frozen")
|
||||
require("ssl")
|
||||
|
@ -1 +1,2 @@
|
||||
require("mip-cmdline")
|
||||
require("ssl")
|
||||
|
@ -0,0 +1 @@
|
||||
require("ssl")
|
@ -1,3 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="14.0">
|
||||
<PropertyGroup>
|
||||
<FrozenManifest>$(PyWinDir)\variants\manifest.py</FrozenManifest>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
@ -1,13 +1,13 @@
|
||||
# Basic test of ssl.SSLContext get_ciphers() and set_ciphers() methods.
|
||||
# Basic test of tls.SSLContext get_ciphers() and set_ciphers() methods.
|
||||
|
||||
try:
|
||||
import ssl
|
||||
import tls
|
||||
except ImportError:
|
||||
print("SKIP")
|
||||
raise SystemExit
|
||||
|
||||
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
||||
ctx = tls.SSLContext(tls.PROTOCOL_TLS_CLIENT)
|
||||
|
||||
ciphers = ctx.get_ciphers()
|
||||
|
@ -1,20 +1,20 @@
|
||||
# Test MicroPython-specific behaviour of ssl.SSLContext.
|
||||
# Test MicroPython-specific behaviour of tls.SSLContext.
|
||||
|
||||
try:
|
||||
import ssl
|
||||
import tls
|
||||
except ImportError:
|
||||
print("SKIP")
|
||||
raise SystemExit
|
||||
|
||||
# Test constructing without any arguments (in CPython it's a DeprecationWarning).
|
||||
try:
|
||||
ssl.SSLContext()
|
||||
tls.SSLContext()
|
||||
except TypeError:
|
||||
print("TypeError")
|
||||
|
||||
# Test attributes that don't exist (in CPython new attributes can be added).
|
||||
# This test is needed for coverage because SSLContext implements a custom attr handler.
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
||||
ctx = tls.SSLContext(tls.PROTOCOL_TLS_CLIENT)
|
||||
try:
|
||||
ctx.does_not_exist
|
||||
except AttributeError:
|
@ -3,7 +3,7 @@
|
||||
try:
|
||||
import os
|
||||
import socket
|
||||
import ssl
|
||||
import tls
|
||||
except ImportError:
|
||||
print("SKIP")
|
||||
raise SystemExit
|
||||
@ -13,6 +13,10 @@ PORT = 8000
|
||||
# These are test certificates. See tests/README.md for details.
|
||||
cert = cafile = "ec_cert.der"
|
||||
key = "ec_key.der"
|
||||
with open(cafile, "rb") as f:
|
||||
cadata = f.read()
|
||||
with open(key, "rb") as f:
|
||||
keydata = f.read()
|
||||
|
||||
try:
|
||||
os.stat(cafile)
|
||||
@ -31,8 +35,8 @@ def instance0():
|
||||
s.listen(1)
|
||||
multitest.next()
|
||||
s2, _ = s.accept()
|
||||
server_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
|
||||
server_ctx.load_cert_chain(cert, key)
|
||||
server_ctx = tls.SSLContext(tls.PROTOCOL_TLS_SERVER)
|
||||
server_ctx.load_cert_chain(cadata, keydata)
|
||||
s2 = server_ctx.wrap_socket(s2, server_side=True)
|
||||
assert isinstance(s2.cipher(), tuple)
|
||||
print(s2.read(16))
|
||||
@ -46,12 +50,12 @@ def instance1():
|
||||
multitest.next()
|
||||
s = socket.socket()
|
||||
s.connect(socket.getaddrinfo(IP, PORT)[0][-1])
|
||||
client_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
||||
client_ctx = tls.SSLContext(tls.PROTOCOL_TLS_CLIENT)
|
||||
ciphers = client_ctx.get_ciphers()
|
||||
assert "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256" in ciphers
|
||||
client_ctx.set_ciphers(["TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256"])
|
||||
client_ctx.verify_mode = ssl.CERT_REQUIRED
|
||||
client_ctx.load_verify_locations(cafile=cafile)
|
||||
client_ctx.verify_mode = tls.CERT_REQUIRED
|
||||
client_ctx.load_verify_locations(cadata)
|
||||
s = client_ctx.wrap_socket(s, server_hostname="micropython.local")
|
||||
s.write(b"client to server")
|
||||
print(s.read(16))
|
||||
|
@ -57,8 +57,8 @@ deflate errno example_package
|
||||
ffi framebuf gc hashlib
|
||||
heapq io json machine
|
||||
math os platform random
|
||||
re select socket ssl
|
||||
struct sys termios time
|
||||
re select socket struct
|
||||
sys termios time tls
|
||||
uctypes websocket
|
||||
me
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user