8000 extmod/modssl_mbedtls: Add SSLContext methods. · micropython/micropython@37a1ffc · GitHub
[go: up one dir, main page]

Skip to content

Commit 37a1ffc

Browse files
committed
extmod/modssl_mbedtls: Add SSLContext methods.
This commit adds a `# MICROPY_SSL_MBEDTLS_EXTRAS` macro that enables: 1) Methods to SSLContext class that match CPython signature: - `SSLContext.load_cert_chain(certfile, keyfile=)` - `SSLContext.load_verify_locations(cadata=)` - `SSLContext.get_ciphers()` --> ["CIPHERSUITE"] - `SSLContext.set_ciphers(["CIPHERSUITE"])` 2) `sslsocket.cipher()` to get current ciphersuite and protocol version. 3) `ssl.MBEDTLS_VERSION` string constant 4) Tests in `net_inet` and `multi_net` Signed-off-by: Carlos Gil <carlosgilglez@gmail.com>
1 parent d529c20 commit 37a1ffc

19 files changed

+1390
-97
lines changed

extmod/modssl_mbedtls.c

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@
4646
#include "mbedtls/ctr_drbg.h"
4747
#include "mbedtls/debug.h"
4848
#include "mbedtls/error.h"
49+
#ifdef MICROPY_SSL_MBEDTLS_EXTRAS
50+
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
51+
#include "mbedtls/build_info.h"
52+
#else
53+
#include "mbedtls/version.h"
54+
#endif
55+
#endif
4956

5057
#define MP_STREAM_POLL_RDWR (MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)
5158

@@ -59,6 +66,9 @@ typedef struct _mp_obj_ssl_context_t {
5966
mbedtls_x509_crt cert;
6067
mbedtls_pk_context pkey;
6168
int authmode;
69+
#ifdef MICROPY_SSL_MBEDTLS_EXTRAS
70+
int cipherid [];
71+
#endif
6272
} mp_obj_ssl_context_t;
6373

6474
// This corresponds to an SSLSocket object.
@@ -74,6 +84,9 @@ typedef struct _mp_obj_ssl_socket_t {
7484

7585
STATIC const mp_obj_type_t ssl_context_type;
7686
STATIC const mp_obj_type_t ssl_socket_type;
87+
#ifdef MICROPY_SSL_MBEDTLS_EXTRAS
88+
STATIC const MP_DEFINE_STR_OBJ(mbedtls_version_obj, MBEDTLS_VERSION_STRING_FULL);
89+
#endif
7790

7891
STATIC mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t sock,
7992
bool server_side, bool do_handshake_on_connect, mp_obj_t server_hostname);
@@ -154,6 +167,9 @@ STATIC mp_obj_t ssl_context_make_new(const mp_obj_type_t *type_in, size_t n_args
154167
mp_obj_ssl_context_t *self = m_new_obj(mp_obj_ssl_context_t);
155168
#endif
156169
self->base.type = type_in;
170+
#ifdef MICROPY_SSL_MBEDTLS_EXTRAS
171+
self->cipherid[0] = 0;
172+
#endif
157173

158174
// Initialise mbedTLS state.
159175
mbedtls_ssl_config_init(&self->conf);
@@ -230,6 +246,57 @@ STATIC mp_obj_t ssl_context___del__(mp_obj_t self_in) {
230246
STATIC MP_DEFINE_CONST_FUN_OBJ_1(ssl_context___del___obj, ssl_context___del__);
231247
#endif
232248

249+
#ifdef MICROPY_SSL_MBEDTLS_EXTRAS
250+
// Ciphersuites
251+
252+
STATIC mp_obj_t mod_ssl_get_ciphers(mp_obj_t self_in) {
253+
mp_obj_t list = mp_obj_new_list(0, NULL);
254+
const int *cipher_list = mbedtls_ssl_list_ciphersuites();
255+
while (*cipher_list) {
256+
const char *cipher_name = mbedtls_ssl_get_ciphersuite_name(*cipher_list);
257+
mp_obj_list_append(list,
258+
MP_OBJ_FROM_PTR(mp_obj_new_str(cipher_name,
259+
strlen(cipher_name))));
260+
cipher_list++;
261+
if (!*cipher_list) {
262+
break;
263+
}
264+
}
265+
return list;
266+
}
267+
268+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ssl_get_ciphers_obj, mod_ssl_get_ciphers);
269+
270+
271+
STATIC mp_obj_t mod_ssl_set_ciphers(mp_obj_t self_in, mp_obj_t ciphersuite) {
272+
// check that ciphersuite is a list
273+
if (mp_obj_is_type(ciphersuite, &mp_type_list)) {
274+
mp_obj_ssl_context_t *self = MP_OBJ_TO_PTR(self_in);
275+
mp_obj_list_t *ciphers = MP_OBJ_TO_PTR(ciphersuite);
276+
277+
for (int i = 0, n = ciphers->len; i < n; i++) {
278+
279+
if (ciphers->items[i] != mp_const_none) {
280+
const char *ciphername = mp_obj_str_get_str(ciphers->items[i]);
281+
const int id = mbedtls_ssl_get_ciphersuite_id(ciphername);
282+
self->cipherid[i] = id;
283+
if (id == 0) {
284+
mbedtls_raise_error(MBEDTLS_ERR_SSL_BAD_CONFIG);
285+
}
286+
}
287+
}
288+
self->cipherid[ciphers->len + 1] = 0;
289+
} else {
290+
mbedtls_raise_error(MBEDTLS_ERR_SSL_BAD_CONFIG);
291+
}
292+
return mp_const_none;
293+
}
294+
295+
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_ssl_set_ciphers_obj, mod_ssl_set_ciphers);
296+
297+
#endif
298+
// SSLContext.load_cert_chain
299+
233300
STATIC void ssl_context_load_key(mp_obj_ssl_context_t *self, mp_obj_t key_obj, mp_obj_t cert_obj) {
234301
size_t key_len;
235302
const byte *key = (const byte *)mp_obj_str_get_data(key_obj, &key_len);
@@ -258,6 +325,32 @@ STATIC void ssl_context_load_key(mp_obj_ssl_context_t *self, mp_obj_t key_obj, m
258325
}
259326
}
260327

328+
#ifdef MICROPY_SSL_MBEDTLS_EXTRAS
329+
330+
STATIC mp_obj_t mod_ssl_load_certchain(size_t n_args, const mp_obj_t *pos_args,
331+
mp_map_t *kw_args) {
332+
333+
static const mp_arg_t allowed_args[] = {
334+
{ MP_QSTR_keyfile, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
335+
};
336+
337+
mp_obj_ssl_context_t *self = MP_OBJ_TO_PTR(pos_args[0]);
338+
mp_obj_t cert = pos_args[1];
339+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
340+
mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
341+
342+
if (cert != mp_const_none) {
343+
mp_check_self(mp_obj_is_str_or_bytes(cert));
344+
mp_check_self(mp_obj_is_str_or_bytes(args[0].u_obj));
345+
ssl_context_load_key(self, args[0].u_obj, cert);
346+
}
347+
return mp_const_none;
348+
}
349+
350+
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_load_certchain_obj, 2, mod_ssl_load_certchain);
351+
#endif
352+
// SSLContext.load_verify_locations
353+
261354
STATIC void ssl_context_load_cadata(mp_obj_ssl_context_t *self, mp_obj_t cadata_obj) {
262355
size_t cacert_len;
263356
const byte *cacert = (const byte *)mp_obj_str_get_data(cadata_obj, &cacert_len);
@@ -270,6 +363,28 @@ STATIC void ssl_context_load_cadata(mp_obj_ssl_context_t *self, mp_obj_t cadata_
270363
mbedtls_ssl_conf_ca_chain(&self->conf, &self->cacert, NULL);
271364
}
272365

366+
#ifdef MICROPY_SSL_MBEDTLS_EXTRAS
367+
STATIC mp_obj_t mod_ssl_load_cadata(size_t n_args, const mp_obj_t *pos_args,
368+
mp_map_t *kw_args) {
369+
370+
static const mp_arg_t allowed_args[] = {
371+
{ MP_QSTR_cadata, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
372+
};
373+
374+
mp_obj_ssl_context_t *self = MP_OBJ_TO_PTR(pos_args[0]);
375+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
376+
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
377+
378+
if (args[0].u_obj != mp_const_none) {
379+
mp_check_self(mp_obj_is_str_or_bytes(args[0].u_obj));
380+
ssl_context_load_cadata(self, args[0].u_obj);
381+
}
382+
return mp_const_none;
383+
}
384+
385+
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_load_cadata_obj, 1, mod_ssl_load_cadata);
386+
#endif
387+
273388
STATIC mp_obj_t ssl_context_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
274389
enum { ARG_server_side, ARG_do_handshake_on_connect, ARG_server_hostname };
275390
static const mp_arg_t allowed_args[] = {
@@ -284,6 +399,12 @@ STATIC mp_obj_t ssl_context_wrap_socket(size_t n_args, const mp_obj_t *pos_args,
284399
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
285400
mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
286401

402+
if (self->authmode == MBEDTLS_SSL_VERIFY_REQUIRED && args[ARG_server_side].u_bool == false) {
403+
404+
if (args[ARG_server_hostname].u_obj == mp_const_none) {
405+
mp_raise_ValueError(MP_ERROR_TEXT("CERT_REQUIRED requires server_hostname"));
406+
}
407+
}
287408
// Create and return the new SSLSocket object.
288409
return ssl_socket_make_new(self, sock, args[ARG_server_side].u_bool,
289410
args[ARG_do_handshake_on_connect].u_bool, args[ARG_server_hostname].u_obj);
@@ -294,6 +415,12 @@ STATIC const mp_rom_map_elem_t ssl_context_locals_dict_table[] = {
294415
#if MICROPY_PY_SSL_FINALISER
295416
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&ssl_context___del___obj) },
296417
#endif
418+
#ifdef MICROPY_SSL_MBEDTLS_EXTRAS
419+
{ MP_ROM_QSTR(MP_QSTR_get_ciphers), MP_ROM_PTR(&mod_ssl_get_ciphers_obj)},
420+
{ MP_ROM_QSTR(MP_QSTR_set_ciphers), MP_ROM_PTR(&mod_ssl_set_ciphers_obj)},
421+
{ MP_ROM_QSTR(MP_QSTR_load_verify_locations), MP_ROM_PTR(&mod_ssl_load_cadata_obj)},
422+
{ MP_ROM_QSTR(MP_QSTR_load_cert_chain), MP_ROM_PTR(&mod_ssl_load_certchain_obj)},
423+
#endif
297424
{ MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&ssl_context_wrap_socket_obj) },
298425
};
299426
STATIC MP_DEFINE_CONST_DICT(ssl_context_locals_dict, ssl_context_locals_dict_table);
@@ -363,6 +490,18 @@ STATIC mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t
363490
o->last_error = 0;
364491

365492
int ret;
493+
#ifdef MICROPY_SSL_MBEDTLS_EXTRAS
494+
uint32_t flags = 0;
495+
int *cid = &ssl_context->cipherid[0];
496+
/* printf("cipherid: %d\n", *cid); */
497+
498+
// Ciphersuite Config
499+
if (*cid != 0) {
500+
mbedtls_ssl_conf_ciphersuites(&ssl_context->conf, (const int *)&ssl_context->cipherid);
501+
}
502+
#endif
503+
504+
366505
mbedtls_ssl_init(&o->ssl);
367506

368507
ret = mbedtls_ssl_setup(&o->ssl, &ssl_context->conf);
@@ -394,7 +533,29 @@ STATIC mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t
394533
return MP_OBJ_FROM_PTR(o);
395534

396535
cleanup:
536+
#ifdef MICROPY_SSL_MBEDTLS_EXTRAS
537+
if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
538+
flags = mbedtls_ssl_get_verify_result(&o->ssl);
539+
}
540+
#endif
541+
542+
397543
mbedtls_ssl_free(&o->ssl);
544+
545+
#ifdef MICROPY_SSL_MBEDTLS_EXTRAS
546+
if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
547+
char xcbuf[512];
548+
ret = mbedtls_x509_crt_verify_info(xcbuf, sizeof(xcbuf), "\n", flags);
549+
// The length of the string written (not including the terminated nul byte),
550+
// or a negative err code.
551+
if (ret > 0) {
552+
mp_raise_ValueError(MP_ERROR_TEXT(xcbuf));
553+
} else {
554+
mbedtls_raise_error(ret);
555+
}
556+
}
557+
#endif
558+
398559
mbedtls_raise_error(ret);
399560
}
400561

@@ -411,6 +572,19 @@ STATIC mp_obj_t mod_ssl_getpeercert(mp_obj_t o_in, mp_obj_t binary_form) {
411572
}
412573
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_ssl_getpeercert_obj, mod_ssl_getpeercert);
413574

575+
#ifdef MICROPY_SSL_MBEDTLS_EXTRAS
576+
STATIC mp_obj_t mod_ssl_cipher(mp_obj_t o_in) {
577+
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
578+
const char *cipher_suite = mbedtls_ssl_get_ciphersuite(&o->ssl);
579+
const char *tls_version = mbedtls_ssl_get_version(&o->ssl);
580+
mp_obj_t tuple[2] = {mp_obj_new_str(cipher_suite, strlen(cipher_suite)),
581+
mp_obj_new_str(tls_version, strlen(tls_version))};
582+
583+
return mp_obj_new_tuple(2, tuple);
584+
}
585+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ssl_cipher_obj, mod_ssl_cipher);
586+
#endif
587+
414588
STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
415589
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
416590
o->poll_mask = 0;
@@ -552,6 +726,9 @@ STATIC const mp_rom_map_elem_t ssl_socket_locals_dict_table[] = {
552726
{ MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) },
553727
#endif
554728
{ MP_ROM_QSTR(MP_QSTR_getpeercert), MP_ROM_PTR(&mod_ssl_getpeercert_obj) },
729+
#ifdef MICROPY_SSL_MBEDTLS_EXTRAS
730+
{ MP_ROM_QSTR(MP_QSTR_cipher), MP_ROM_PTR(&mod_ssl_cipher_obj) },
731+
#endif
555732
};
556733
STATIC MP_DEFINE_CONST_DICT(ssl_socket_locals_dict, ssl_socket_locals_dict_table);
557734

@@ -632,6 +809,9 @@ STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = {
632809
{ MP_ROM_QSTR(MP_QSTR_SSLContext), MP_ROM_PTR(&ssl_context_type) },
633810

634811
// Constants.
812+
#ifdef MICROPY_SSL_MBEDTLS_EXTRAS
813+
{ MP_ROM_QSTR(MP_QSTR_MBEDTLS_VERSION), MP_ROM_PTR(&mbedtls_version_obj)},
814+
#endif
635815
{ MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLS_CLIENT), MP_ROM_INT(MBEDTLS_SSL_IS_CLIENT) },
636816
{ MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLS_SERVER), MP_ROM_INT(MBEDTLS_SSL_IS_SERVER) },
637817
{ MP_ROM_QSTR(MP_QSTR_CERT_NONE), MP_ROM_INT(MBEDTLS_SSL_VERIFY_NONE) },

ports/unix/mpconfigport.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,3 +251,7 @@ static inline unsigned long mp_random_seed_init(void) {
251251
#ifndef MICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS
252252
#define MICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS (MICROPY_BLUETOOTH_NIMBLE)
253253
#endif
254+
255+
#ifndef MICROPY_SSL_MBEDTLS_EXTRAS
256+
#define MICROPY_SSL_MBEDTLS_EXTRAS (1)
257+
#endif

0 commit comments

Comments
 (0)
0