Skip to content

Adds TLS-PSK support to Python SSL context #14396

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions extmod/mbedtls/mbedtls_config_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
#define MBEDTLS_CAN_ECDH
#define MBEDTLS_PK_CAN_ECDSA_SIGN
#define MBEDTLS_PKCS1_V15
Expand Down
50 changes: 50 additions & 0 deletions extmod/modtls_mbedtls.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,24 @@ static int ssl_sock_cert_verify(void *ptr, mbedtls_x509_crt *crt, int depth, uin
return mp_obj_get_int(mp_call_function_2(o->handler, MP_OBJ_FROM_PTR(&cert), MP_OBJ_NEW_SMALL_INT(depth)));
}

static int ssl_conf_psk_cb(void *parameter, mbedtls_ssl_context *ssl,
const unsigned char *psk_identity, size_t psk_identity_len) {
mp_obj_t callback = MP_OBJ_FROM_PTR(parameter);
mp_obj_t psk_identity_obj = mp_obj_new_bytes(psk_identity, psk_identity_len);

// Call the callback
mp_obj_t psk_key_obj = mp_call_function_1(callback, psk_identity_obj);

// Check if psk key object is supplied, set handshake psk
int ret = -1;
if (psk_key_obj != mp_const_none) {
size_t psk_key_len;
const unsigned char *psk_key = (const unsigned char *)mp_obj_str_get_data(psk_key_obj, &psk_key_len);
ret = mbedtls_ssl_set_hs_psk(ssl, psk_key, psk_key_len);
}
return ret;
}

/******************************************************************************/
// SSLContext type.

Expand Down Expand Up @@ -401,6 +419,36 @@ static mp_obj_t ssl_context_load_verify_locations(mp_obj_t self_in, mp_obj_t cad
}
static MP_DEFINE_CONST_FUN_OBJ_2(ssl_context_load_verify_locations_obj, ssl_context_load_verify_locations);

// SSLContext.set_psk_server_callback(callback)
static mp_obj_t ssl_context_set_psk_server_callback(mp_obj_t self_in, mp_obj_t callback) {
mp_obj_ssl_context_t *self = MP_OBJ_TO_PTR(self_in);

// Check if callback is supplied, config psk callback
if (callback != mp_const_none) {
mbedtls_ssl_conf_psk_cb(&self->conf, ssl_conf_psk_cb, MP_OBJ_TO_PTR(callback));
}
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_2(ssl_context_set_psk_server_callback_obj, ssl_context_set_psk_server_callback);

// SSLContext.set_psk_client_callback(callback)
static mp_obj_t ssl_context_set_psk_client_callback(mp_obj_t self_in, mp_obj_t callback) {
mp_obj_ssl_context_t *self = MP_OBJ_TO_PTR(self_in);

// Check if callback is supplied, config psk
if (callback != mp_const_none) {
mp_obj_tuple_t *psk_pairwise_obj = MP_OBJ_TO_PTR(mp_call_function_1(callback, mp_const_none));
if (psk_pairwise_obj->len == 2) {
size_t psk_identity_len, psk_key_len;
const unsigned char *psk_identity = (const unsigned char *)mp_obj_str_get_data(psk_pairwise_obj->items[0], &psk_identity_len);
const unsigned char *psk_key = (const unsigned char *)mp_obj_str_get_data(psk_pairwise_obj->items[1], &psk_key_len);
mbedtls_ssl_conf_psk(&self->conf, psk_key, psk_key_len, psk_identity, psk_identity_len);
}
}
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_2(ssl_context_set_psk_client_callback_obj, ssl_context_set_psk_client_callback);

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 };
static const mp_arg_t allowed_args[] = {
Expand Down Expand Up @@ -429,6 +477,8 @@ static const mp_rom_map_elem_t ssl_context_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_set_ciphers), MP_ROM_PTR(&ssl_context_set_ciphers_obj)},
{ MP_ROM_QSTR(MP_QSTR_load_cert_chain), MP_ROM_PTR(&ssl_context_load_cert_chain_obj)},
{ MP_ROM_QSTR(MP_QSTR_load_verify_locations), MP_ROM_PTR(&ssl_context_load_verify_locations_obj)},
{ MP_ROM_QSTR(MP_QSTR_set_psk_server_callback), MP_ROM_PTR(&ssl_context_set_psk_server_callback_obj)},
{ MP_ROM_QSTR(MP_QSTR_set_psk_client_callback), MP_ROM_PTR(&ssl_context_set_psk_client_callback_obj)},
{ MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&ssl_context_wrap_socket_obj) },
};
static MP_DEFINE_CONST_DICT(ssl_context_locals_dict, ssl_context_locals_dict_table);
Expand Down
7 changes: 7 additions & 0 deletions ports/esp32/boards/sdkconfig.base
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=n
# significant factor in overall physical security.)
CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC=y

# Enable MBEDTLS to support TLS-PSK
CONFIG_MBEDTLS_PSK_MODES=y
CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y
CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK=y
CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK=y
CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK=y

# ULP coprocessor support
# Only on: ESP32, ESP32S2, ESP32S3
CONFIG_ULP_COPROC_ENABLED=y
Expand Down
53 changes: 53 additions & 0 deletions tests/multi_net/sslcontext_server_client_with_psk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Test asyncio TCP server and client with TLS-PSK, using set_psk_sever_callback() and set_psk_client_callback().

try:
import socket
import tls
except ImportError:
print("SKIP")
raise SystemExit

PORT = 8000


# Server
def instance0():
multitest.globals(IP=multitest.get_network_ip())
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(socket.getaddrinfo("0.0.0.0", PORT)[0][-1])
s.listen(1)
multitest.next()
s2, _ = s.accept()
server_ctx = tls.SSLContext(tls.PROTOCOL_TLS_SERVER)

def psk_server_callback(identity):
psk_dict = {
b"PSK-Identity-1": bytes.fromhex("c0ffee"),
b"PSK-Identity-2": bytes.fromhex("facade"),
}
return psk_dict[identity]

server_ctx.set_psk_server_callback(psk_server_callback)
s2 = server_ctx.wrap_socket(s2, server_side=True)
print(s2.read(16))
s2.write(b"server to client")
s2.close()
s.close()


# Client
def instance1():
multitest.next()
s = socket.socket()
s.connect(socket.getaddrinfo(IP, PORT)[0][-1])
client_ctx = tls.SSLContext(tls.PROTOCOL_TLS_CLIENT)

def psk_client_callback(identity):
return (b"PSK-Identity-1", bytes.fromhex("c0ffee"))

client_ctx.set_psk_client_callback(psk_client_callback)
s = client_ctx.wrap_socket(s, server_hostname="micropython.local")
s.write(b"client to server")
print(s.read(16))
s.close()
4 changes: 4 additions & 0 deletions tests/multi_net/sslcontext_server_client_with_psk.py.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
--- instance0 ---
b'client to server'
--- instance1 ---
b'server to client'
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy