More ssl work

This commit is contained in:
Jeff Epler 2022-10-05 14:32:30 -05:00
parent 944d388158
commit fabfdcf6fe
No known key found for this signature in database
GPG Key ID: D5BF15AB975AB4DE
9 changed files with 138 additions and 69 deletions

View File

@ -350,12 +350,17 @@ SRC_MBEDTLS := $(addprefix lib/mbedtls/library/, \
x509write_csr.c \ x509write_csr.c \
xtea.c \ xtea.c \
) )
SRC_C += $(SRC_MBEDTLS) mbedtls/mbedtls_port.c SRC_C += $(SRC_MBEDTLS) mbedtls/mbedtls_port.c mbedtls/crt_bundle.c
CFLAGS += \ CFLAGS += \
-isystem $(TOP)/lib/mbedtls/include \ -isystem $(TOP)/lib/mbedtls/include \
-DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"' \ -DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"' \
$(BUILD)/x509_crt_bundle.S: $(TOP)/lib/certificates/nina-fw/data/roots.pem $(TOP)/tools/gen_crt_bundle.py
$(Q)$(PYTHON) $(TOP)/tools/gen_crt_bundle.py -i $< -o $@ --asm
OBJ_MBEDTLS := $(BUILD)/x509_crt_bundle.o
$(patsubst %.c,$(BUILD)/%.o,$(SRC_MBEDTLS))): CFLAGS += -Wno-suggest-attribute=format $(patsubst %.c,$(BUILD)/%.o,$(SRC_MBEDTLS))): CFLAGS += -Wno-suggest-attribute=format
else
OBJ_MBEDTLS :=
endif endif
SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \
@ -396,9 +401,9 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_S_UPPER:.S=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_S_UPPER:.S=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o))
OBJ += $(BUILD)/boot2_padded_checksummed.o OBJ += $(BUILD)/boot2_padded_checksummed.o
OBJ += $(OBJ_CYW43) OBJ += $(OBJ_CYW43) $(OBJ_MBEDTLS)
$(BUILD)/boot2_padded_checksummed.o: $(BUILD)/boot2_padded_checksummed.S $(BUILD)/%.o: $(BUILD)/%.S
$(STEPECHO) "CC $<" $(STEPECHO) "CC $<"
$(Q)$(CC) $(CFLAGS) -c -o $@ $< $(Q)$(CC) $(CFLAGS) -c -o $@ $<

View File

@ -31,16 +31,27 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "py/stream.h" #include "py/stream.h"
#include "mbedtls/crt_bundle.h"
void common_hal_ssl_sslcontext_construct(ssl_sslcontext_obj_t *self) { void common_hal_ssl_sslcontext_construct(ssl_sslcontext_obj_t *self) {
common_hal_ssl_sslcontext_set_default_verify_paths(self);
} }
void common_hal_ssl_sslcontext_load_verify_locations(ssl_sslcontext_obj_t *self, void common_hal_ssl_sslcontext_load_verify_locations(ssl_sslcontext_obj_t *self,
const char *cadata) { const char *cadata) {
mp_raise_NotImplementedError(NULL); mp_raise_NotImplementedError(NULL);
// self->crt_bundle_attach = NULL;
// self->use_global_ca_store = false;
// self->cacert_buf = (const unsigned char *)cadata;
// self->cacert_bytes = strlen(cadata) + 1;
} }
void common_hal_ssl_sslcontext_set_default_verify_paths(ssl_sslcontext_obj_t *self) { void common_hal_ssl_sslcontext_set_default_verify_paths(ssl_sslcontext_obj_t *self) {
mp_raise_NotImplementedError(NULL); self->crt_bundle_attach = crt_bundle_attach;
self->use_global_ca_store = true;
self->cacert_buf = NULL;
self->cacert_bytes = 0;
} }
bool common_hal_ssl_sslcontext_get_check_hostname(ssl_sslcontext_obj_t *self) { bool common_hal_ssl_sslcontext_get_check_hostname(ssl_sslcontext_obj_t *self) {

View File

@ -28,8 +28,12 @@
#pragma once #pragma once
#include "py/obj.h" #include "py/obj.h"
#include "mbedtls/ssl.h"
typedef struct { typedef struct {
mp_obj_base_t base; mp_obj_base_t base;
bool check_name; bool check_name, use_global_ca_store;
const unsigned char *cacert_buf;
size_t cacert_bytes;
int (*crt_bundle_attach)(mbedtls_ssl_config *conf);
} ssl_sslcontext_obj_t; } ssl_sslcontext_obj_t;

View File

@ -171,8 +171,15 @@ ssl_sslsocket_obj_t *common_hal_ssl_sslcontext_wrap_socket(ssl_sslcontext_obj_t
goto cleanup; goto cleanup;
} }
// no certificate checking now if (self->crt_bundle_attach != NULL) {
mbedtls_ssl_conf_authmode(&o->conf, MBEDTLS_SSL_VERIFY_NONE); mp_printf(&mp_plat_print, "attaching bundle\n");
mbedtls_ssl_conf_authmode(&o->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
self->crt_bundle_attach(&o->conf);
// } else if(self->cacert_buf && self->cacert_bytes) { // TODO: user bundle
} else {
mp_printf(&mp_plat_print, "yolo\n");
mbedtls_ssl_conf_authmode(&o->conf, MBEDTLS_SSL_VERIFY_NONE);
}
mbedtls_ssl_conf_rng(&o->conf, mbedtls_ctr_drbg_random, &o->ctr_drbg); mbedtls_ssl_conf_rng(&o->conf, mbedtls_ctr_drbg_random, &o->ctr_drbg);
#ifdef MBEDTLS_DEBUG_C #ifdef MBEDTLS_DEBUG_C
mbedtls_ssl_conf_dbg(&o->conf, mbedtls_debug, NULL); mbedtls_ssl_conf_dbg(&o->conf, mbedtls_debug, NULL);

View File

@ -25,8 +25,15 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#include "common-hal/ssl/__init__.h"
#include "shared-bindings/ssl/__init__.h" #include "shared-bindings/ssl/__init__.h"
#include "shared-bindings/ssl/SSLContext.h" #include "shared-bindings/ssl/SSLContext.h"
#include "mbedtls/crt_bundle.h"
void common_hal_ssl_create_default_context(ssl_sslcontext_obj_t *self) { void common_hal_ssl_create_default_context(ssl_sslcontext_obj_t *self) {
common_hal_ssl_sslcontext_construct(self);
}
void ssl_reset(void) {
crt_bundle_detach(NULL);
} }

View File

@ -25,3 +25,5 @@
*/ */
#pragma once #pragma once
void ssl_reset(void);

View File

@ -1,4 +1,5 @@
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD // Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
// Copyright 2022 Jeff Epler for Adafruit Industries
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -12,24 +13,35 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#define BUNDLE_MAX_CERTS (200)
#include <string.h> #include <string.h>
#include <esp_system.h>
#include "esp_crt_bundle.h" #include "py/runtime.h"
#include "esp_log.h" #include "py/mperrno.h"
#include "mbedtls/x509_crt.h"
#include "mbedtls/crt_bundle.h"
#define BUNDLE_HEADER_OFFSET 2 #define BUNDLE_HEADER_OFFSET 2
#define CRT_HEADER_OFFSET 4 #define CRT_HEADER_OFFSET 4
static const char *TAG = "esp-x509-crt-bundle";
/* a dummy certificate so that /* a dummy certificate so that
* cacert_ptr passes non-NULL check during handshake */ * cacert_ptr passes non-NULL check during handshake */
static mbedtls_x509_crt s_dummy_crt; static mbedtls_x509_crt s_dummy_crt;
#define TAG "x509-crt-bundle"
extern const uint8_t x509_crt_imported_bundle_bin_start[] asm("_binary_x509_crt_bundle_start"); #define LOGE(tag, fmt, ...) mp_printf(&mp_plat_print, tag ":" fmt "\n",##__VA_ARGS__)
extern const uint8_t x509_crt_imported_bundle_bin_end[] asm("_binary_x509_crt_bundle_end"); #if 0
#define LOGI(tag, fmt, ...) mp_printf(&mp_plat_print, tag ":" fmt "\n",##__VA_ARGS__)
#define LOGD(tag, fmt, ...) mp_printf(&mp_plat_print, tag ":" fmt "\n",##__VA_ARGS__)
#else
#define LOGI(tag, fmt, ...) do {} while (0)
#define LOGD(tag, fmt, ...) do {} while (0)
#endif
extern const uint8_t x509_crt_imported_bundle_bin_start[] asm ("_binary_x509_crt_bundle_start");
extern const uint8_t x509_crt_imported_bundle_bin_end[] asm ("_binary_x509_crt_bundle_end");
typedef struct crt_bundle_t { typedef struct crt_bundle_t {
@ -40,11 +52,10 @@ typedef struct crt_bundle_t {
static crt_bundle_t s_crt_bundle; static crt_bundle_t s_crt_bundle;
static int esp_crt_check_signature(mbedtls_x509_crt *child, const uint8_t *pub_key_buf, size_t pub_key_len); static int crt_check_signature(mbedtls_x509_crt *child, const uint8_t *pub_key_buf, size_t pub_key_len);
static int esp_crt_check_signature(mbedtls_x509_crt *child, const uint8_t *pub_key_buf, size_t pub_key_len) static int crt_check_signature(mbedtls_x509_crt *child, const uint8_t *pub_key_buf, size_t pub_key_len) {
{
int ret = 0; int ret = 0;
mbedtls_x509_crt parent; mbedtls_x509_crt parent;
const mbedtls_md_info_t *md_info; const mbedtls_md_info_t *md_info;
@ -52,30 +63,30 @@ static int esp_crt_check_signature(mbedtls_x509_crt *child, const uint8_t *pub_k
mbedtls_x509_crt_init(&parent); mbedtls_x509_crt_init(&parent);
if ( (ret = mbedtls_pk_parse_public_key(&parent.pk, pub_key_buf, pub_key_len) ) != 0) { if ((ret = mbedtls_pk_parse_public_key(&parent.pk, pub_key_buf, pub_key_len)) != 0) {
ESP_LOGE(TAG, "PK parse failed with error %X", ret); LOGE(TAG, "PK parse failed with error %X", ret);
goto cleanup; goto cleanup;
} }
// Fast check to avoid expensive computations when not necessary // Fast check to avoid expensive computations when not necessary
if (!mbedtls_pk_can_do(&parent.pk, child->sig_pk)) { if (!mbedtls_pk_can_do(&parent.pk, child->sig_pk)) {
ESP_LOGE(TAG, "Simple compare failed"); LOGE(TAG, "Simple compare failed");
ret = -1; ret = -1;
goto cleanup; goto cleanup;
} }
md_info = mbedtls_md_info_from_type(child->sig_md); md_info = mbedtls_md_info_from_type(child->sig_md);
if ( (ret = mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash )) != 0 ) { if ((ret = mbedtls_md(md_info, child->tbs.p, child->tbs.len, hash)) != 0) {
ESP_LOGE(TAG, "Internal mbedTLS error %X", ret); LOGE(TAG, "Internal mbedTLS error %X", ret);
goto cleanup; goto cleanup;
} }
if ( (ret = mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent.pk, if ((ret = mbedtls_pk_verify_ext(child->sig_pk, child->sig_opts, &parent.pk,
child->sig_md, hash, mbedtls_md_get_size( md_info ), child->sig_md, hash, mbedtls_md_get_size(md_info),
child->sig.p, child->sig.len )) != 0 ) { child->sig.p, child->sig.len)) != 0) {
ESP_LOGE(TAG, "PK verify failed with error %X", ret); LOGE(TAG, "PK verify failed with error %X", ret);
goto cleanup; goto cleanup;
} }
cleanup: cleanup:
@ -91,8 +102,7 @@ cleanup:
* only verify the first untrusted link in the chain is signed by the * only verify the first untrusted link in the chain is signed by the
* root certificate in the trusted bundle * root certificate in the trusted bundle
*/ */
int esp_crt_verify_callback(void *buf, mbedtls_x509_crt *crt, int depth, uint32_t *flags) static int crt_verify_callback(void *buf, mbedtls_x509_crt *crt, int depth, uint32_t *flags) {
{
mbedtls_x509_crt *child = crt; mbedtls_x509_crt *child = crt;
/* It's OK for a trusted cert to have a weak signature hash alg. /* It's OK for a trusted cert to have a weak signature hash alg.
@ -105,11 +115,11 @@ int esp_crt_verify_callback(void *buf, mbedtls_x509_crt *crt, int depth, uint32_
if (s_crt_bundle.crts == NULL) { if (s_crt_bundle.crts == NULL) {
ESP_LOGE(TAG, "No certificates in bundle"); LOGE(TAG, "No certificates in bundle");
return MBEDTLS_ERR_X509_FATAL_ERROR; return MBEDTLS_ERR_X509_FATAL_ERROR;
} }
ESP_LOGD(TAG, "%d certificates in bundle", s_crt_bundle.num_certs); LOGD(TAG, "%d certificates in bundle", s_crt_bundle.num_certs);
size_t name_len = 0; size_t name_len = 0;
const uint8_t *crt_name; const uint8_t *crt_name;
@ -124,7 +134,7 @@ int esp_crt_verify_callback(void *buf, mbedtls_x509_crt *crt, int depth, uint32_
name_len = s_crt_bundle.crts[middle][0] << 8 | s_crt_bundle.crts[middle][1]; name_len = s_crt_bundle.crts[middle][0] << 8 | s_crt_bundle.crts[middle][1];
crt_name = s_crt_bundle.crts[middle] + CRT_HEADER_OFFSET; crt_name = s_crt_bundle.crts[middle] + CRT_HEADER_OFFSET;
int cmp_res = memcmp(child->issuer_raw.p, crt_name, name_len ); int cmp_res = memcmp(child->issuer_raw.p, crt_name, name_len);
if (cmp_res == 0) { if (cmp_res == 0) {
crt_found = true; crt_found = true;
break; break;
@ -139,16 +149,16 @@ int esp_crt_verify_callback(void *buf, mbedtls_x509_crt *crt, int depth, uint32_
int ret = MBEDTLS_ERR_X509_FATAL_ERROR; int ret = MBEDTLS_ERR_X509_FATAL_ERROR;
if (crt_found) { if (crt_found) {
size_t key_len = s_crt_bundle.crts[middle][2] << 8 | s_crt_bundle.crts[middle][3]; size_t key_len = s_crt_bundle.crts[middle][2] << 8 | s_crt_bundle.crts[middle][3];
ret = esp_crt_check_signature(child, s_crt_bundle.crts[middle] + CRT_HEADER_OFFSET + name_len, key_len); ret = crt_check_signature(child, s_crt_bundle.crts[middle] + CRT_HEADER_OFFSET + name_len, key_len);
} }
if (ret == 0) { if (ret == 0) {
ESP_LOGI(TAG, "Certificate validated"); LOGI(TAG, "Certificate validated");
*flags = 0; *flags = 0;
return 0; return 0;
} }
ESP_LOGE(TAG, "Failed to verify certificate"); LOGE(TAG, "Failed to verify certificate");
return MBEDTLS_ERR_X509_FATAL_ERROR; return MBEDTLS_ERR_X509_FATAL_ERROR;
} }
@ -156,25 +166,24 @@ int esp_crt_verify_callback(void *buf, mbedtls_x509_crt *crt, int depth, uint32_
/* Initialize the bundle into an array so we can do binary search for certs, /* Initialize the bundle into an array so we can do binary search for certs,
the bundle generated by the python utility is already presorted by subject name the bundle generated by the python utility is already presorted by subject name
*/ */
static esp_err_t esp_crt_bundle_init(const uint8_t *x509_bundle, size_t bundle_size) static err_t crt_bundle_init(const uint8_t *x509_bundle, size_t bundle_size) {
{
if (bundle_size < BUNDLE_HEADER_OFFSET + CRT_HEADER_OFFSET) { if (bundle_size < BUNDLE_HEADER_OFFSET + CRT_HEADER_OFFSET) {
ESP_LOGE(TAG, "Invalid certificate bundle"); LOGE(TAG, "Invalid certificate bundle");
return ESP_ERR_INVALID_ARG; return -MP_EINVAL;
} }
uint16_t num_certs = (x509_bundle[0] << 8) | x509_bundle[1]; uint16_t num_certs = (x509_bundle[0] << 8) | x509_bundle[1];
if (num_certs > CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS) { if (num_certs > BUNDLE_MAX_CERTS) {
ESP_LOGE(TAG, "No. of certs in the certificate bundle = %d exceeds\n" // No. of certs in the certificate bundle = %d exceeds\n"
"Max allowed certificates in the certificate bundle = %d\n" // Max allowed certificates in the certificate bundle = %d\n"
"Please update the menuconfig option with appropriate value", num_certs, CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS); // Please update the menuconfig option with appropriate value", num_certs, BUNDLE_MAX_CERTS
return ESP_ERR_INVALID_ARG; return -MP_E2BIG;
} }
const uint8_t **crts = calloc(num_certs, sizeof(x509_bundle)); const uint8_t **crts = m_tracked_calloc(num_certs, sizeof(x509_bundle));
if (crts == NULL) { if (crts == NULL) {
ESP_LOGE(TAG, "Unable to allocate memory for bundle"); LOGE(TAG, "Unable to allocate memory for bundle");
return ESP_ERR_NO_MEM; return -MP_ENOMEM;
} }
const uint8_t *cur_crt; const uint8_t *cur_crt;
@ -185,9 +194,9 @@ static esp_err_t esp_crt_bundle_init(const uint8_t *x509_bundle, size_t bundle_s
for (int i = 0; i < num_certs; i++) { for (int i = 0; i < num_certs; i++) {
crts[i] = cur_crt; crts[i] = cur_crt;
if (cur_crt + CRT_HEADER_OFFSET > bundle_end) { if (cur_crt + CRT_HEADER_OFFSET > bundle_end) {
ESP_LOGE(TAG, "Invalid certificate bundle"); LOGE(TAG, "Invalid certificate bundle");
free(crts); m_tracked_free(crts);
return ESP_ERR_INVALID_ARG; return -MP_EINVAL;
} }
size_t name_len = cur_crt[0] << 8 | cur_crt[1]; size_t name_len = cur_crt[0] << 8 | cur_crt[1];
size_t key_len = cur_crt[2] << 8 | cur_crt[3]; size_t key_len = cur_crt[2] << 8 | cur_crt[3];
@ -195,57 +204,52 @@ static esp_err_t esp_crt_bundle_init(const uint8_t *x509_bundle, size_t bundle_s
} }
if (cur_crt > bundle_end) { if (cur_crt > bundle_end) {
ESP_LOGE(TAG, "Invalid certificate bundle"); LOGE(TAG, "Invalid certificate bundle");
free(crts); m_tracked_free(crts);
return ESP_ERR_INVALID_ARG; return -MP_EINVAL;
} }
/* The previous crt bundle is only updated when initialization of the /* The previous crt bundle is only updated when initialization of the
* current crt_bundle is successful */ * current crt_bundle is successful */
/* Free previous crt_bundle */ /* Free previous crt_bundle */
free(s_crt_bundle.crts); m_tracked_free(s_crt_bundle.crts);
s_crt_bundle.num_certs = num_certs; s_crt_bundle.num_certs = num_certs;
s_crt_bundle.crts = crts; s_crt_bundle.crts = crts;
return ESP_OK; return 0;
} }
esp_err_t esp_crt_bundle_attach(void *conf) int crt_bundle_attach(mbedtls_ssl_config *ssl_conf) {
{ int ret = 0;
esp_err_t ret = ESP_OK;
// If no bundle has been set by the user then use the bundle embedded in the binary // If no bundle has been set by the user then use the bundle embedded in the binary
if (s_crt_bundle.crts == NULL) { if (s_crt_bundle.crts == NULL) {
ret = esp_crt_bundle_init(x509_crt_imported_bundle_bin_start, x509_crt_imported_bundle_bin_end - x509_crt_imported_bundle_bin_start); ret = crt_bundle_init(x509_crt_imported_bundle_bin_start, x509_crt_imported_bundle_bin_end - x509_crt_imported_bundle_bin_start);
} }
if (ret != ESP_OK) { if (ret != 0) {
ESP_LOGE(TAG, "Failed to attach bundle");
return ret; return ret;
} }
if (conf) { if (ssl_conf) {
/* point to a dummy certificate /* point to a dummy certificate
* This is only required so that the * This is only required so that the
* cacert_ptr passes non-NULL check during handshake * cacert_ptr passes non-NULL check during handshake
*/ */
mbedtls_ssl_config *ssl_conf = (mbedtls_ssl_config *)conf;
mbedtls_x509_crt_init(&s_dummy_crt); mbedtls_x509_crt_init(&s_dummy_crt);
mbedtls_ssl_conf_ca_chain(ssl_conf, &s_dummy_crt, NULL); mbedtls_ssl_conf_ca_chain(ssl_conf, &s_dummy_crt, NULL);
mbedtls_ssl_conf_verify(ssl_conf, esp_crt_verify_callback, NULL); mbedtls_ssl_conf_verify(ssl_conf, crt_verify_callback, NULL);
} }
return ret; return ret;
} }
void esp_crt_bundle_detach(mbedtls_ssl_config *conf) void crt_bundle_detach(mbedtls_ssl_config *conf) {
{ m_tracked_free(s_crt_bundle.crts);
free(s_crt_bundle.crts);
s_crt_bundle.crts = NULL; s_crt_bundle.crts = NULL;
if (conf) { if (conf) {
mbedtls_ssl_conf_verify(conf, NULL, NULL); mbedtls_ssl_conf_verify(conf, NULL, NULL);
} }
} }
esp_err_t esp_crt_bundle_set(const uint8_t *x509_bundle, size_t bundle_size) int crt_bundle_set(const uint8_t *x509_bundle, size_t bundle_size) {
{ return crt_bundle_init(x509_bundle, bundle_size);
return esp_crt_bundle_init(x509_bundle, bundle_size);
} }

View File

@ -0,0 +1,21 @@
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
// Copyright 2022 Jeff Epler for Adafruit Industries
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include "mbedtls/ssl.h"
int crt_bundle_attach(mbedtls_ssl_config *conf);
void crt_bundle_detach(mbedtls_ssl_config *conf);
int crt_bundle_set(const uint8_t *x509_bundle, size_t bundle_size);

View File

@ -41,6 +41,10 @@
#include "shared-bindings/rtc/__init__.h" #include "shared-bindings/rtc/__init__.h"
#include "shared-bindings/pwmio/PWMOut.h" #include "shared-bindings/pwmio/PWMOut.h"
#if CIRCUITPY_SSL
#include "common-hal/ssl/__init__.h"
#endif
#if CIRCUITPY_WIFI #if CIRCUITPY_WIFI
#include "common-hal/wifi/__init__.h" #include "common-hal/wifi/__init__.h"
#endif #endif
@ -179,6 +183,10 @@ void reset_port(void) {
audio_dma_reset(); audio_dma_reset();
#endif #endif
#if CIRCUITPY_SSL
ssl_reset();
#endif
#if CIRCUITPY_WIFI #if CIRCUITPY_WIFI
wifi_reset(); wifi_reset();
#endif #endif