From f7eaa5f9467da8261b7ed55413a1d2c6d6913817 Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Sat, 7 Sep 2019 16:24:54 +0530 Subject: [PATCH 1/2] ESP_TLS: Restructuring esp_tls 1)Segregating mbedtls API into seperate file and cleaned esp_tls.c 2)Added support for wolfssl for CMake and make 3)Added support for debug_wolfssl (with menuconfig option) 4)Added info on wolfssl in ESP-TLS docs --- components/esp-tls/CMakeLists.txt | 18 +- components/esp-tls/Kconfig | 37 +- components/esp-tls/component.mk | 13 + components/esp-tls/esp_tls.c | 794 +++++------------- components/esp-tls/esp_tls.h | 55 +- components/esp-tls/esp_tls_mbedtls.c | 547 ++++++++++++ components/esp-tls/esp_tls_wolfssl.c | 244 ++++++ .../esp_tls_error_capture_internal.h | 14 +- .../esp-tls/private_include/esp_tls_mbedtls.h | 104 +++ .../esp-tls/private_include/esp_tls_wolfssl.h | 72 ++ docs/en/api-reference/protocols/esp_tls.rst | 80 +- 11 files changed, 1345 insertions(+), 633 deletions(-) create mode 100644 components/esp-tls/esp_tls_mbedtls.c create mode 100644 components/esp-tls/esp_tls_wolfssl.c create mode 100644 components/esp-tls/private_include/esp_tls_mbedtls.h create mode 100644 components/esp-tls/private_include/esp_tls_wolfssl.h diff --git a/components/esp-tls/CMakeLists.txt b/components/esp-tls/CMakeLists.txt index ea6b61216..bf32e96ea 100644 --- a/components/esp-tls/CMakeLists.txt +++ b/components/esp-tls/CMakeLists.txt @@ -1,5 +1,21 @@ -idf_component_register(SRCS "esp_tls.c" +set(srcs esp_tls.c) +if(CONFIG_ESP_TLS_USING_MBEDTLS) + list(APPEND srcs + "esp_tls_mbedtls.c") +endif() + +if(CONFIG_ESP_TLS_USING_WOLFSSL) + list(APPEND srcs + "esp_tls_wolfssl.c") +endif() + +idf_component_register(SRCS "${srcs}" INCLUDE_DIRS "." PRIV_INCLUDE_DIRS "private_include" REQUIRES mbedtls PRIV_REQUIRES lwip nghttp) + +if(CONFIG_ESP_TLS_USING_WOLFSSL) + idf_component_get_property(wolfssl esp-wolfssl COMPONENT_LIB) + target_link_libraries(${COMPONENT_LIB} PUBLIC ${wolfssl}) +endif() diff --git a/components/esp-tls/Kconfig b/components/esp-tls/Kconfig index e31ac8de7..7c5e5626d 100644 --- a/components/esp-tls/Kconfig +++ b/components/esp-tls/Kconfig @@ -1,12 +1,28 @@ menu "ESP-TLS" + choice ESP_TLS_LIBRARY_CHOOSE + prompt "Choose SSL/TLS library for ESP-TLS (See help for more Info)" + default ESP_TLS_USING_MBEDTLS + help + The ESP-TLS APIs support multiple backend TLS libraries. Currently mbedTLS and WolfSSL are + supported. Different TLS libraries may support different features and have different resource + usage. Consult the ESP-TLS documentation in ESP-IDF Programming guide for more details. + config ESP_TLS_USING_MBEDTLS + bool "mbedTLS" + config ESP_TLS_USING_WOLFSSL + depends on TLS_STACK_WOLFSSL + bool "wolfSSL (License info in wolfSSL directory README)" + endchoice config ESP_TLS_SERVER bool "Enable ESP-TLS Server" + depends on ESP_TLS_USING_MBEDTLS + default n help - Enable support for creating server side SSL/TLS session + Enable support for creating server side SSL/TLS session, uses the mbedtls crypto library config ESP_TLS_PSK_VERIFICATION bool "Enable PSK verification" + depends on ESP_TLS_USING_MBEDTLS select MBEDTLS_PSK_MODES select MBEDTLS_KEY_EXCHANGE_PSK select MBEDTLS_KEY_EXCHANGE_DHE_PSK @@ -14,7 +30,22 @@ menu "ESP-TLS" select MBEDTLS_KEY_EXCHANGE_RSA_PSK default n help - Enable support for pre shared key ciphers + Enable support for pre shared key ciphers, uses the mbedtls crypto library + + config ESP_WOLFSSL_SMALL_CERT_VERIFY + bool "Enable SMALL_CERT_VERIFY" + depends on ESP_TLS_USING_WOLFSSL + default y + help + Enables server verification with Intermediate CA cert, does not authenticate full chain + of trust upto the root CA cert (After Enabling this option client only needs to have Intermediate + CA certificate of the server to authenticate server, root CA cert is not necessary). + + config ESP_DEBUG_WOLFSSL + bool "Enable debug logs for wolfSSL" + depends on ESP_TLS_USING_WOLFSSL + default n + help + Enable detailed debug prints for wolfSSL SSL library. endmenu - diff --git a/components/esp-tls/component.mk b/components/esp-tls/component.mk index 06991cd1c..70f6f2fa7 100644 --- a/components/esp-tls/component.mk +++ b/components/esp-tls/component.mk @@ -1,3 +1,16 @@ + COMPONENT_SRCDIRS := . +COMPONENT_OBJS := esp_tls.o COMPONENT_ADD_INCLUDEDIRS := . private_include + + +ifneq ($(CONFIG_ESP_TLS_USING_MBEDTLS), ) +COMPONENT_OBJS += esp_tls_mbedtls.o +endif + +ifneq ($(CONFIG_ESP_TLS_USING_WOLFSSL), ) +COMPONENT_OBJS += esp_tls_wolfssl.o +endif + +CFLAGS += -DWOLFSSL_USER_SETTINGS diff --git a/components/esp-tls/esp_tls.c b/components/esp-tls/esp_tls.c index 39c048196..af2be302d 100644 --- a/components/esp-tls/esp_tls.c +++ b/components/esp-tls/esp_tls.c @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -24,9 +24,13 @@ #include "esp_tls.h" #include "esp_tls_error_capture_internal.h" #include - static const char *TAG = "esp-tls"; -static mbedtls_x509_crt *global_cacert = NULL; + +#ifdef CONFIG_ESP_TLS_USING_MBEDTLS +#include "esp_tls_mbedtls.h" +#elif CONFIG_ESP_TLS_USING_WOLFSSL +#include "esp_tls_wolfssl.h" +#endif #ifdef ESP_PLATFORM #include @@ -35,16 +39,86 @@ static mbedtls_x509_crt *global_cacert = NULL; #define ESP_LOGE(TAG, ...) printf(__VA_ARGS__); #endif -typedef struct esp_tls_pki_t { - mbedtls_x509_crt *public_cert; - mbedtls_pk_context *pk_key; - const unsigned char *publiccert_pem_buf; - unsigned int publiccert_pem_bytes; - const unsigned char *privkey_pem_buf; - unsigned int privkey_pem_bytes; - const unsigned char *privkey_password; - unsigned int privkey_password_len; -} esp_tls_pki_t; +#ifdef CONFIG_ESP_TLS_USING_MBEDTLS +#define _esp_create_ssl_handle esp_create_mbedtls_handle +#define _esp_tls_handshake esp_mbedtls_handshake +#define _esp_tls_read esp_mbedtls_read +#define _esp_tls_write esp_mbedtls_write +#define _esp_tls_conn_delete esp_mbedtls_conn_delete +#ifdef CONFIG_ESP_TLS_SERVER +#define _esp_tls_server_session_create esp_mbedtls_server_session_create +#define _esp_tls_server_session_delete esp_mbedtls_server_session_delete +#endif /* CONFIG_ESP_TLS_SERVER */ +#define _esp_tls_get_bytes_avail esp_mbedtls_get_bytes_avail +#define _esp_tls_init_global_ca_store esp_mbedtls_init_global_ca_store +#define _esp_tls_set_global_ca_store esp_mbedtls_set_global_ca_store /*!< Callback function for setting global CA store data for TLS/SSL */ +#define _esp_tls_get_global_ca_store esp_mbedtls_get_global_ca_store +#define _esp_tls_free_global_ca_store esp_mbedtls_free_global_ca_store /*!< Callback function for freeing global ca store for TLS/SSL */ +#elif CONFIG_ESP_TLS_USING_WOLFSSL /* CONFIG_ESP_TLS_USING_MBEDTLS */ +#define _esp_create_ssl_handle esp_create_wolfssl_handle +#define _esp_tls_handshake esp_wolfssl_handshake +#define _esp_tls_read esp_wolfssl_read +#define _esp_tls_write esp_wolfssl_write +#define _esp_tls_conn_delete esp_wolfssl_conn_delete +#define _esp_tls_get_bytes_avail esp_wolfssl_get_bytes_avail +#define _esp_tls_init_global_ca_store esp_wolfssl_init_global_ca_store +#define _esp_tls_set_global_ca_store esp_wolfssl_set_global_ca_store /*!< Callback function for setting global CA store data for TLS/SSL */ +#define _esp_tls_free_global_ca_store esp_wolfssl_free_global_ca_store /*!< Callback function for freeing global ca store for TLS/SSL */ +#else /* ESP_TLS_USING_WOLFSSL */ +#error "No TLS stack configured" +#endif + +static esp_err_t create_ssl_handle(const char *hostname, size_t hostlen, const void *cfg, esp_tls_t *tls) +{ + return _esp_create_ssl_handle(hostname, hostlen, cfg, tls); +} + +static esp_err_t esp_tls_handshake(esp_tls_t *tls, const esp_tls_cfg_t *cfg) +{ + return _esp_tls_handshake(tls, cfg); +} + +static ssize_t tcp_read(esp_tls_t *tls, char *data, size_t datalen) +{ + return recv(tls->sockfd, data, datalen, 0); +} + +static ssize_t tcp_write(esp_tls_t *tls, const char *data, size_t datalen) +{ + return send(tls->sockfd, data, datalen, 0); +} + +/** + * @brief Close the TLS connection and free any allocated resources. + */ +void esp_tls_conn_delete(esp_tls_t *tls) +{ + if (tls != NULL) { + _esp_tls_conn_delete(tls); + if (tls->sockfd >= 0) { + close(tls->sockfd); + } + free(tls->error_handle); + free(tls); + } +} + +esp_tls_t *esp_tls_init(void) +{ + esp_tls_t *tls = (esp_tls_t *)calloc(1, sizeof(esp_tls_t)); + if (!tls) { + return NULL; + } + tls->error_handle = calloc(1, sizeof(esp_tls_last_error_t)); + if (!tls->error_handle) { + free(tls); + return NULL; + } +#ifdef CONFIG_ESP_TLS_USING_MBEDTLS + tls->server_fd.fd = tls->sockfd = -1; +#endif + return tls; +} static esp_err_t resolve_host_name(const char *host, size_t hostlen, struct addrinfo **address_info) { @@ -68,26 +142,6 @@ static esp_err_t resolve_host_name(const char *host, size_t hostlen, struct addr return ESP_OK; } -static ssize_t tcp_read(esp_tls_t *tls, char *data, size_t datalen) -{ - return recv(tls->sockfd, data, datalen, 0); -} - -static ssize_t tls_read(esp_tls_t *tls, char *data, size_t datalen) -{ - ssize_t ret = mbedtls_ssl_read(&tls->ssl, (unsigned char *)data, datalen); - if (ret < 0) { - if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { - return 0; - } - if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); - ESP_LOGE(TAG, "read error :%d:", ret); - } - } - return ret; -} - static void ms_to_timeval(int timeout_ms, struct timeval *tv) { tv->tv_sec = timeout_ms / 1000; @@ -159,426 +213,6 @@ err_freeaddr: return ret; } -esp_err_t esp_tls_init_global_ca_store(void) -{ - if (global_cacert == NULL) { - global_cacert = (mbedtls_x509_crt *)calloc(1, sizeof(mbedtls_x509_crt)); - if (global_cacert == NULL) { - ESP_LOGE(TAG, "global_cacert not allocated"); - return ESP_ERR_NO_MEM; - } - mbedtls_x509_crt_init(global_cacert); - } - return ESP_OK; -} - -esp_err_t esp_tls_set_global_ca_store(const unsigned char *cacert_pem_buf, const unsigned int cacert_pem_bytes) -{ - int ret; - if (cacert_pem_buf == NULL) { - ESP_LOGE(TAG, "cacert_pem_buf is null"); - return ESP_ERR_INVALID_ARG; - } - if (global_cacert == NULL) { - ret = esp_tls_init_global_ca_store(); - if (ret != ESP_OK) { - return ret; - } - } - ret = mbedtls_x509_crt_parse(global_cacert, cacert_pem_buf, cacert_pem_bytes); - if (ret < 0) { - ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x", -ret); - mbedtls_x509_crt_free(global_cacert); - global_cacert = NULL; - return ESP_FAIL; - } else if (ret > 0) { - ESP_LOGE(TAG, "mbedtls_x509_crt_parse was partly successful. No. of failed certificates: %d", ret); - return ESP_ERR_MBEDTLS_CERT_PARTLY_OK; - } - return ESP_OK; -} - -mbedtls_x509_crt *esp_tls_get_global_ca_store(void) -{ - return global_cacert; -} - -void esp_tls_free_global_ca_store(void) -{ - if (global_cacert) { - mbedtls_x509_crt_free(global_cacert); - global_cacert = NULL; - } -} - -static void verify_certificate(esp_tls_t *tls) -{ - int flags; - char buf[100]; - if ((flags = mbedtls_ssl_get_verify_result(&tls->ssl)) != 0) { - ESP_LOGI(TAG, "Failed to verify peer certificate!"); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS_CERT_FLAGS, flags); - bzero(buf, sizeof(buf)); - mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", flags); - ESP_LOGI(TAG, "verification info: %s", buf); - } else { - ESP_LOGI(TAG, "Certificate verified."); - } -} - -static void mbedtls_cleanup(esp_tls_t *tls) -{ - if (!tls) { - return; - } - if (tls->cacert_ptr != global_cacert) { - mbedtls_x509_crt_free(tls->cacert_ptr); - } - tls->cacert_ptr = NULL; -#ifdef CONFIG_ESP_TLS_SERVER - mbedtls_x509_crt_free(&tls->servercert); - mbedtls_pk_free(&tls->serverkey); -#endif - mbedtls_x509_crt_free(&tls->cacert); - mbedtls_x509_crt_free(&tls->clientcert); - mbedtls_pk_free(&tls->clientkey); - mbedtls_entropy_free(&tls->entropy); - mbedtls_ssl_config_free(&tls->conf); - mbedtls_ctr_drbg_free(&tls->ctr_drbg); - mbedtls_ssl_free(&tls->ssl); -} - -static esp_err_t set_global_ca_store(esp_tls_t *tls) -{ - assert(tls); - if (global_cacert == NULL) { - ESP_LOGE(TAG, "global_cacert is NULL"); - return ESP_ERR_INVALID_STATE; - } - tls->cacert_ptr = global_cacert; - mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); - mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); - return ESP_OK; -} - -static esp_err_t set_ca_cert(esp_tls_t *tls, const unsigned char *cacert, size_t cacert_len) -{ - assert(tls); - tls->cacert_ptr = &tls->cacert; - mbedtls_x509_crt_init(tls->cacert_ptr); - int ret = mbedtls_x509_crt_parse(tls->cacert_ptr, cacert, cacert_len); - if (ret < 0) { - ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); - return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED; - } - mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); - mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); - return ESP_OK; -} - -static esp_err_t set_pki_context(esp_tls_t *tls, const esp_tls_pki_t *pki) -{ - assert(tls); - assert(pki); - int ret; - - if (pki->publiccert_pem_buf != NULL && - pki->privkey_pem_buf != NULL && - pki->public_cert != NULL && - pki->pk_key != NULL) { - - mbedtls_x509_crt_init(pki->public_cert); - mbedtls_pk_init(pki->pk_key); - - ret = mbedtls_x509_crt_parse(pki->public_cert, pki->publiccert_pem_buf, pki->publiccert_pem_bytes); - if (ret < 0) { - ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); - return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED; - } - - ret = mbedtls_pk_parse_key(pki->pk_key, pki->privkey_pem_buf, pki->privkey_pem_bytes, - NULL, 0); - if (ret < 0) { - ESP_LOGE(TAG, "mbedtls_pk_parse_keyfile returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); - return ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED; - } - - ret = mbedtls_ssl_conf_own_cert(&tls->conf, pki->public_cert, pki->pk_key); - if (ret < 0) { - ESP_LOGE(TAG, "mbedtls_ssl_conf_own_cert returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); - return ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED; - } - } else { - return ESP_ERR_INVALID_ARG; - } - return ESP_OK; -} - -#ifdef CONFIG_ESP_TLS_SERVER -static esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls) -{ - assert(cfg != NULL); - assert(tls != NULL); - int ret; - esp_err_t esp_ret; - if ((ret = mbedtls_ssl_config_defaults(&tls->conf, - MBEDTLS_SSL_IS_SERVER, - MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned %d", ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); - return ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED; - } - -#ifdef CONFIG_MBEDTLS_SSL_ALPN - if (cfg->alpn_protos) { - mbedtls_ssl_conf_alpn_protocols(&tls->conf, cfg->alpn_protos); - } -#endif - - if (cfg->cacert_buf != NULL) { - esp_ret = set_ca_cert(tls, cfg->cacert_buf, cfg->cacert_bytes); - if (esp_ret != ESP_OK) { - return esp_ret; - } - } else { - mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_NONE); - } - - if (cfg->servercert_buf != NULL && cfg->serverkey_buf != NULL) { - esp_tls_pki_t pki = { - .public_cert = &tls->servercert, - .pk_key = &tls->serverkey, - .publiccert_pem_buf = cfg->servercert_buf, - .publiccert_pem_bytes = cfg->servercert_bytes, - .privkey_pem_buf = cfg->serverkey_buf, - .privkey_pem_bytes = cfg->serverkey_bytes, - .privkey_password = cfg->serverkey_password, - .privkey_password_len = cfg->serverkey_password_len, - }; - esp_ret = set_pki_context(tls, &pki); - if (esp_ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to set server pki context"); - return esp_ret; - } - } else { - ESP_LOGE(TAG, "Missing server certificate and/or key"); - return ESP_ERR_INVALID_STATE; - } - return ESP_OK; -} -#endif /* ! CONFIG_ESP_TLS_SERVER */ - -static esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t *cfg, esp_tls_t *tls) -{ - assert(cfg != NULL); - assert(tls != NULL); - int ret; - if (!cfg->skip_common_name) { - char *use_host = NULL; - if (cfg->common_name != NULL) { - use_host = strndup(cfg->common_name, strlen(cfg->common_name)); - } else { - use_host = strndup(hostname, hostlen); - } - - if (use_host == NULL) { - return ESP_ERR_NO_MEM; - } - /* Hostname set here should match CN in server certificate */ - if ((ret = mbedtls_ssl_set_hostname(&tls->ssl, use_host)) != 0) { - ESP_LOGE(TAG, "mbedtls_ssl_set_hostname returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); - free(use_host); - return ESP_ERR_MBEDTLS_SSL_SET_HOSTNAME_FAILED; - } - free(use_host); - } - - if ((ret = mbedtls_ssl_config_defaults(&tls->conf, - MBEDTLS_SSL_IS_CLIENT, - MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); - return ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED; - } - -#ifdef CONFIG_MBEDTLS_SSL_ALPN - if (cfg->alpn_protos) { - if ((ret =mbedtls_ssl_conf_alpn_protocols(&tls->conf, cfg->alpn_protos) != 0)) { - ESP_LOGE(TAG, "mbedtls_ssl_conf_alpn_protocols returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); - return ESP_ERR_MBEDTLS_SSL_CONF_ALPN_PROTOCOLS_FAILED; - } - } -#endif - if (cfg->use_global_ca_store == true) { - esp_err_t esp_ret = set_global_ca_store(tls); - if (esp_ret != ESP_OK) { - return esp_ret; - } - } else if (cfg->cacert_buf != NULL) { - esp_err_t esp_ret = set_ca_cert(tls, cfg->cacert_buf, cfg->cacert_bytes); - if (esp_ret != ESP_OK) { - return esp_ret; - } - mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); - } else if (cfg->psk_hint_key) { -#if defined(CONFIG_ESP_TLS_PSK_VERIFICATION) - // - // PSK encryption mode is configured only if no certificate supplied and psk pointer not null - ESP_LOGD(TAG, "ssl psk authentication"); - ret = mbedtls_ssl_conf_psk(&tls->conf, cfg->psk_hint_key->key, cfg->psk_hint_key->key_size, - (const unsigned char *)cfg->psk_hint_key->hint, strlen(cfg->psk_hint_key->hint)); - if (ret != 0) { - ESP_LOGE(TAG, "mbedtls_ssl_conf_psk returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); - return ESP_ERR_MBEDTLS_SSL_CONF_PSK_FAILED; - } -#else - ESP_LOGE(TAG, "psk_hint_key configured but not enabled in menuconfig: Please enable ESP_TLS_PSK_VERIFICATION option"); - return ESP_ERR_INVALID_STATE; -#endif - } else { - mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_NONE); - } - - if (cfg->clientcert_buf != NULL && cfg->clientkey_buf != NULL) { - esp_tls_pki_t pki = { - .public_cert = &tls->clientcert, - .pk_key = &tls->clientkey, - .publiccert_pem_buf = cfg->clientcert_buf, - .publiccert_pem_bytes = cfg->clientcert_bytes, - .privkey_pem_buf = cfg->clientkey_buf, - .privkey_pem_bytes = cfg->clientkey_bytes, - .privkey_password = cfg->clientkey_password, - .privkey_password_len = cfg->clientkey_password_len, - }; - esp_err_t esp_ret = set_pki_context(tls, &pki); - if (esp_ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to set client pki context"); - return esp_ret; - } - } else if (cfg->clientcert_buf != NULL || cfg->clientkey_buf != NULL) { - ESP_LOGE(TAG, "You have to provide both clientcert_buf and clientkey_buf for mutual authentication"); - return ESP_ERR_INVALID_STATE; - } - return ESP_OK; -} - -static esp_err_t create_ssl_handle(const char *hostname, size_t hostlen, const void *cfg, esp_tls_t *tls) -{ - assert(cfg != NULL); - assert(tls != NULL); - int ret; - esp_err_t esp_ret; - tls->server_fd.fd = tls->sockfd; - mbedtls_ssl_init(&tls->ssl); - mbedtls_ctr_drbg_init(&tls->ctr_drbg); - mbedtls_ssl_config_init(&tls->conf); - mbedtls_entropy_init(&tls->entropy); - - if (tls->role == ESP_TLS_CLIENT) { - esp_ret = set_client_config(hostname, hostlen, (esp_tls_cfg_t *)cfg, tls); - if (esp_ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to set client configurations"); - goto exit; - } -#ifdef CONFIG_ESP_TLS_SERVER - } else if (tls->role == ESP_TLS_SERVER) { - esp_ret = set_server_config((esp_tls_cfg_server_t *) cfg, tls); - if (esp_ret != 0) { - ESP_LOGE(TAG, "Failed to set server configurations"); - goto exit; - } -#endif - } - - if ((ret = mbedtls_ctr_drbg_seed(&tls->ctr_drbg, - mbedtls_entropy_func, &tls->entropy, NULL, 0)) != 0) { - ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); - esp_ret = ESP_ERR_MBEDTLS_CTR_DRBG_SEED_FAILED; - goto exit; - } - - mbedtls_ssl_conf_rng(&tls->conf, mbedtls_ctr_drbg_random, &tls->ctr_drbg); - -#ifdef CONFIG_MBEDTLS_DEBUG - mbedtls_esp_enable_debug_log(&tls->conf, CONFIG_MBEDTLS_DEBUG_LEVEL); -#endif - - if ((ret = mbedtls_ssl_setup(&tls->ssl, &tls->conf)) != 0) { - ESP_LOGE(TAG, "mbedtls_ssl_setup returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); - esp_ret = ESP_ERR_MBEDTLS_SSL_SETUP_FAILED; - goto exit; - } - mbedtls_ssl_set_bio(&tls->ssl, &tls->server_fd, mbedtls_net_send, mbedtls_net_recv, NULL); - - return ESP_OK; -exit: - mbedtls_cleanup(tls); - return esp_ret; -} - -/** - * @brief Close the TLS connection and free any allocated resources. - */ -void esp_tls_conn_delete(esp_tls_t *tls) -{ - if (tls != NULL) { - mbedtls_cleanup(tls); - if (tls->is_tls) { - mbedtls_net_free(&tls->server_fd); - } else if (tls->sockfd >= 0) { - close(tls->sockfd); - } - free(tls->error_handle); - free(tls); - } -}; - -static ssize_t tcp_write(esp_tls_t *tls, const char *data, size_t datalen) -{ - return send(tls->sockfd, data, datalen, 0); -} - -static ssize_t tls_write(esp_tls_t *tls, const char *data, size_t datalen) -{ - size_t written = 0; - size_t write_len = datalen; - while (written < datalen) { - if (write_len > MBEDTLS_SSL_OUT_CONTENT_LEN) { - write_len = MBEDTLS_SSL_OUT_CONTENT_LEN; - } - if (datalen > MBEDTLS_SSL_OUT_CONTENT_LEN) { - ESP_LOGD(TAG, "Fragmenting data of excessive size :%d, offset: %d, size %d", datalen, written, write_len); - } - ssize_t ret = mbedtls_ssl_write(&tls->ssl, (unsigned char*) data + written, write_len); - if (ret <= 0) { - if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != 0) { - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_MBEDTLS_SSL_WRITE_FAILED); - ESP_LOGE(TAG, "write error :%d:", ret); - return ret; - } else { - // Exitting the tls-write process as less than desired datalen are writable - ESP_LOGD(TAG, "mbedtls_ssl_write() returned %d, already written %d, exitting...", ret, written); - return written; - } - } - written += ret; - write_len = datalen - written; - } - return written; -} - static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_t *tls) { if (!tls) { @@ -586,101 +220,82 @@ static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, c return -1; } esp_err_t esp_ret; - int ret; - /* These states are used to keep a tab on connection progress in case of non-blocking connect, and in case of blocking connect these cases will get executed one after the other */ switch (tls->conn_state) { - case ESP_TLS_INIT: - tls->sockfd = -1; - if (cfg != NULL) { - mbedtls_net_init(&tls->server_fd); - tls->is_tls = true; - } - if ((esp_ret = esp_tcp_connect(hostname, hostlen, port, &tls->sockfd, tls, cfg)) != ESP_OK) { - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, esp_ret); - return -1; - } - if (!cfg) { - tls->read = tcp_read; - tls->write = tcp_write; - ESP_LOGD(TAG, "non-tls connection established"); - return 1; - } - if (cfg->non_block) { - FD_ZERO(&tls->rset); - FD_SET(tls->sockfd, &tls->rset); - tls->wset = tls->rset; - } - tls->conn_state = ESP_TLS_CONNECTING; - /* falls through */ - case ESP_TLS_CONNECTING: - if (cfg->non_block) { - ESP_LOGD(TAG, "connecting..."); - struct timeval tv; - ms_to_timeval(cfg->timeout_ms, &tv); + case ESP_TLS_INIT: + tls->sockfd = -1; + if (cfg != NULL) { +#ifdef CONFIG_ESP_TLS_USING_MBEDTLS + mbedtls_net_init(&tls->server_fd); +#endif + tls->is_tls = true; + } + if ((esp_ret = esp_tcp_connect(hostname, hostlen, port, &tls->sockfd, tls, cfg)) != ESP_OK) { + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, esp_ret); + return -1; + } + if (!cfg) { + tls->read = tcp_read; + tls->write = tcp_write; + ESP_LOGD(TAG, "non-tls connection established"); + return 1; + } + if (cfg->non_block) { + FD_ZERO(&tls->rset); + FD_SET(tls->sockfd, &tls->rset); + tls->wset = tls->rset; + } + tls->conn_state = ESP_TLS_CONNECTING; + /* falls through */ + case ESP_TLS_CONNECTING: + if (cfg->non_block) { + ESP_LOGD(TAG, "connecting..."); + struct timeval tv; + ms_to_timeval(cfg->timeout_ms, &tv); - /* In case of non-blocking I/O, we use the select() API to check whether - connection has been estbalished or not*/ - if (select(tls->sockfd + 1, &tls->rset, &tls->wset, NULL, - cfg->timeout_ms ? &tv : NULL) == 0) { - ESP_LOGD(TAG, "select() timed out"); - return 0; - } - if (FD_ISSET(tls->sockfd, &tls->rset) || FD_ISSET(tls->sockfd, &tls->wset)) { - int error; - unsigned int len = sizeof(error); - /* pending error check */ - if (getsockopt(tls->sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { - ESP_LOGD(TAG, "Non blocking connect failed"); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_SYSTEM, errno); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED); - tls->conn_state = ESP_TLS_FAIL; - return -1; - } - } + /* In case of non-blocking I/O, we use the select() API to check whether + connection has been estbalished or not*/ + if (select(tls->sockfd + 1, &tls->rset, &tls->wset, NULL, + cfg->timeout_ms ? &tv : NULL) == 0) { + ESP_LOGD(TAG, "select() timed out"); + return 0; } - /* By now, the connection has been established */ - esp_ret = create_ssl_handle(hostname, hostlen, cfg, tls); - if (esp_ret != ESP_OK) { - ESP_LOGE(TAG, "create_ssl_handle failed"); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, esp_ret); - tls->conn_state = ESP_TLS_FAIL; - return -1; - } - tls->read = tls_read; - tls->write = tls_write; - tls->conn_state = ESP_TLS_HANDSHAKE; - /* falls through */ - case ESP_TLS_HANDSHAKE: - ESP_LOGD(TAG, "handshake in progress..."); - ret = mbedtls_ssl_handshake(&tls->ssl); - if (ret == 0) { - tls->conn_state = ESP_TLS_DONE; - return 1; - } else { - if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - ESP_LOGE(TAG, "mbedtls_ssl_handshake returned -0x%x", -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED); - if (cfg->cacert_buf != NULL || cfg->use_global_ca_store == true) { - /* This is to check whether handshake failed due to invalid certificate*/ - verify_certificate(tls); - } + if (FD_ISSET(tls->sockfd, &tls->rset) || FD_ISSET(tls->sockfd, &tls->wset)) { + int error; + unsigned int len = sizeof(error); + /* pending error check */ + if (getsockopt(tls->sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { + ESP_LOGD(TAG, "Non blocking connect failed"); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_SYSTEM, errno); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED); tls->conn_state = ESP_TLS_FAIL; return -1; } - /* Irrespective of blocking or non-blocking I/O, we return on getting MBEDTLS_ERR_SSL_WANT_READ - or MBEDTLS_ERR_SSL_WANT_WRITE during handshake */ - return 0; } - break; - case ESP_TLS_FAIL: - ESP_LOGE(TAG, "failed to open a new connection");; - break; - default: - ESP_LOGE(TAG, "invalid esp-tls state"); - break; + } + /* By now, the connection has been established */ + esp_ret = create_ssl_handle(hostname, hostlen, cfg, tls); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "create_ssl_handle failed"); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, esp_ret); + tls->conn_state = ESP_TLS_FAIL; + return -1; + } + tls->read = _esp_tls_read; + tls->write = _esp_tls_write; + tls->conn_state = ESP_TLS_HANDSHAKE; + /* falls through */ + case ESP_TLS_HANDSHAKE: + ESP_LOGD(TAG, "handshake in progress..."); + return esp_tls_handshake(tls, cfg); + break; + case ESP_TLS_FAIL: + ESP_LOGE(TAG, "failed to open a new connection");; + break; + default: + ESP_LOGE(TAG, "invalid esp-tls state"); + break; } return -1; } @@ -728,7 +343,7 @@ int esp_tls_conn_new_sync(const char *hostname, int hostlen, int port, const esp /* * @brief Create a new TLS/SSL non-blocking connection */ -int esp_tls_conn_new_async(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg , esp_tls_t *tls) +int esp_tls_conn_new_async(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_t *tls) { return esp_tls_low_level_conn(hostname, hostlen, port, cfg, tls); } @@ -757,24 +372,17 @@ esp_tls_t *esp_tls_conn_http_new(const char *url, const esp_tls_cfg_t *cfg) http_parser_url_init(&u); http_parser_parse_url(url, strlen(url), 0, &u); esp_tls_t *tls = esp_tls_init(); - if (!tls) return NULL; + if (!tls) { + return NULL; + } /* Connect to host */ if (esp_tls_conn_new_sync(&url[u.field_data[UF_HOST].off], u.field_data[UF_HOST].len, - get_port(url, &u), cfg, tls) == 1) { + get_port(url, &u), cfg, tls) == 1) { return tls; } return NULL; } -ssize_t esp_tls_get_bytes_avail(esp_tls_t *tls) -{ - if (!tls) { - ESP_LOGE(TAG, "empty arg passed to esp_tls_get_bytes_avail()"); - return -1; - } - return mbedtls_ssl_get_bytes_avail(&tls->ssl); -} - /** * @brief Create a new non-blocking TLS/SSL connection with a given "HTTP" url */ @@ -787,78 +395,66 @@ int esp_tls_conn_http_new_async(const char *url, const esp_tls_cfg_t *cfg, esp_t /* Connect to host */ return esp_tls_conn_new_async(&url[u.field_data[UF_HOST].off], u.field_data[UF_HOST].len, - get_port(url, &u), cfg, tls); + get_port(url, &u), cfg, tls); +} + +#ifdef CONFIG_ESP_TLS_USING_MBEDTLS + +mbedtls_x509_crt *esp_tls_get_global_ca_store(void) +{ + return _esp_tls_get_global_ca_store(); } #ifdef CONFIG_ESP_TLS_SERVER /** - * @brief Create TLS/SSL server session + * @brief Create a server side TLS/SSL connection */ int esp_tls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp_tls_t *tls) { - if (tls == NULL || cfg == NULL) { - return -1; - } - tls->role = ESP_TLS_SERVER; - tls->sockfd = sockfd; - esp_err_t esp_ret = create_ssl_handle(NULL, 0, cfg, tls); - if (esp_ret != ESP_OK) { - ESP_LOGE(TAG, "create_ssl_handle failed"); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, esp_ret); - tls->conn_state = ESP_TLS_FAIL; - return -1; - } - tls->read = tls_read; - tls->write = tls_write; - int ret; - while ((ret = mbedtls_ssl_handshake(&tls->ssl)) != 0) { - if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - ESP_LOGE(TAG, "mbedtls_ssl_handshake returned %d", ret); - tls->conn_state = ESP_TLS_FAIL; - return ret; - } - } - return 0; + return _esp_tls_server_session_create(cfg, sockfd, tls); } /** * @brief Close the server side TLS/SSL connection and free any allocated resources. */ void esp_tls_server_session_delete(esp_tls_t *tls) { - if (tls != NULL) { - mbedtls_cleanup(tls); - free(tls); - } -}; -#endif /* ! CONFIG_ESP_TLS_SERVER */ + return _esp_tls_server_session_delete(tls); +} +#endif /* CONFIG_ESP_TLS_SERVER */ +#endif /* CONFIG_ESP_TLS_USING_MBEDTLS */ -esp_tls_t *esp_tls_init(void) +ssize_t esp_tls_get_bytes_avail(esp_tls_t *tls) { - esp_tls_t *tls = (esp_tls_t *)calloc(1, sizeof(esp_tls_t)); - if (!tls) { - return NULL; - } - tls->error_handle = calloc(1, sizeof(esp_tls_last_error_t)); - if (!tls->error_handle) { - free(tls); - return NULL; - } - tls->server_fd.fd = tls->sockfd = -1; - return tls; + return _esp_tls_get_bytes_avail(tls); } -esp_err_t esp_tls_get_and_clear_last_error(esp_tls_error_handle_t h, int *mbedtls_code, int *mbedtls_flags) +esp_err_t esp_tls_get_and_clear_last_error(esp_tls_error_handle_t h, int *esp_tls_code, int *esp_tls_flags) { if (!h) { return ESP_ERR_INVALID_STATE; } esp_err_t last_err = h->last_error; - if (mbedtls_code) { - *mbedtls_code = h->mbedtls_error_code; + if (esp_tls_code) { + *esp_tls_code = h->esp_tls_error_code; } - if (mbedtls_flags) { - *mbedtls_flags = h->mbedtls_flags; + if (esp_tls_flags) { + *esp_tls_flags = h->esp_tls_flags; } memset(h, 0, sizeof(esp_tls_last_error_t)); return last_err; } + +esp_err_t esp_tls_init_global_ca_store(void) +{ + return _esp_tls_init_global_ca_store(); +} + +esp_err_t esp_tls_set_global_ca_store(const unsigned char *cacert_pem_buf, const unsigned int cacert_pem_bytes) +{ + return _esp_tls_set_global_ca_store(cacert_pem_buf, cacert_pem_bytes); +} + +void esp_tls_free_global_ca_store(void) +{ + return _esp_tls_free_global_ca_store(); +} diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h index 4d6861498..c92d8cdf8 100644 --- a/components/esp-tls/esp_tls.h +++ b/components/esp-tls/esp_tls.h @@ -18,7 +18,7 @@ #include #include #include "esp_err.h" - +#ifdef CONFIG_ESP_TLS_USING_MBEDTLS #include "mbedtls/platform.h" #include "mbedtls/net_sockets.h" #include "mbedtls/esp_debug.h" @@ -27,6 +27,10 @@ #include "mbedtls/ctr_drbg.h" #include "mbedtls/error.h" #include "mbedtls/certs.h" +#elif CONFIG_ESP_TLS_USING_WOLFSSL +#include "wolfssl/wolfcrypt/settings.h" +#include "wolfssl/ssl.h" +#endif #ifdef __cplusplus extern "C" { @@ -58,8 +62,8 @@ typedef struct esp_tls_last_error* esp_tls_error_handle_t; */ typedef struct esp_tls_last_error { esp_err_t last_error; /*!< error code (based on ESP_ERR_ESP_TLS_BASE) of the last occurred error */ - int mbedtls_error_code; /*!< mbedtls error code from last mbedtls failed api */ - int mbedtls_flags; /*!< last certification verification flags */ + int esp_tls_error_code; /*!< esp_tls error code from last esp_tls failed api */ + int esp_tls_flags; /*!< last certification verification flags */ } esp_tls_last_error_t; /** @@ -236,6 +240,7 @@ typedef struct esp_tls_cfg_server { * @brief ESP-TLS Connection Handle */ typedef struct esp_tls { +#ifdef CONFIG_ESP_TLS_USING_MBEDTLS mbedtls_ssl_context ssl; /*!< TLS/SSL context */ mbedtls_entropy_context entropy; /*!< mbedTLS entropy context structure */ @@ -263,6 +268,10 @@ typedef struct esp_tls { mbedtls_pk_context serverkey; /*!< Container for the private key of the server certificate */ +#endif +#elif CONFIG_ESP_TLS_USING_WOLFSSL + void *priv_ctx; + void *priv_ssl; #endif int sockfd; /*!< Underlying socket file descriptor. */ @@ -491,20 +500,6 @@ esp_err_t esp_tls_init_global_ca_store(void); */ esp_err_t esp_tls_set_global_ca_store(const unsigned char *cacert_pem_buf, const unsigned int cacert_pem_bytes); -/** - * @brief Get the pointer to the global CA store currently being used. - * - * The application must first call esp_tls_set_global_ca_store(). Then the same - * CA store could be used by the application for APIs other than esp_tls. - * - * @note Modifying the pointer might cause a failure in verifying the certificates. - * - * @return - * - Pointer to the global CA store currently being used if successful. - * - NULL if there is no global CA store set. - */ -mbedtls_x509_crt *esp_tls_get_global_ca_store(void); - /** * @brief Free the global CA store currently being used. * @@ -518,17 +513,32 @@ void esp_tls_free_global_ca_store(void); * The error information is cleared internally upon return * * @param[in] h esp-tls error handle. - * @param[out] mbedtls_code last error code returned from mbedtls api (set to zero if none) - * This pointer could be NULL if caller does not care about mbedtls_code - * @param[out] mbedtls_flags last certification verification flags (set to zero if none) - * This pointer could be NULL if caller does not care about mbedtls_flags + * @param[out] esp_tls_code last error code returned from mbedtls api (set to zero if none) + * This pointer could be NULL if caller does not care about esp_tls_code + * @param[out] esp_tls_flags last certification verification flags (set to zero if none) + * This pointer could be NULL if caller does not care about esp_tls_code * * @return * - ESP_ERR_INVALID_STATE if invalid parameters * - ESP_OK (0) if no error occurred * - specific error code (based on ESP_ERR_ESP_TLS_BASE) otherwise */ -esp_err_t esp_tls_get_and_clear_last_error(esp_tls_error_handle_t h, int *mbedtls_code, int *mbedtls_flags); +esp_err_t esp_tls_get_and_clear_last_error(esp_tls_error_handle_t h, int *esp_tls_code, int *esp_tls_flags); + +#if CONFIG_ESP_TLS_USING_MBEDTLS +/** + * @brief Get the pointer to the global CA store currently being used. + * + * The application must first call esp_tls_set_global_ca_store(). Then the same + * CA store could be used by the application for APIs other than esp_tls. + * + * @note Modifying the pointer might cause a failure in verifying the certificates. + * + * @return + * - Pointer to the global CA store currently being used if successful. + * - NULL if there is no global CA store set. + */ +mbedtls_x509_crt *esp_tls_get_global_ca_store(void); #ifdef CONFIG_ESP_TLS_SERVER /** @@ -557,6 +567,7 @@ int esp_tls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp_tls */ void esp_tls_server_session_delete(esp_tls_t *tls); #endif /* ! CONFIG_ESP_TLS_SERVER */ +#endif /* CONFIG_ESP_TLS_USING_MBEDTLS */ #ifdef __cplusplus } diff --git a/components/esp-tls/esp_tls_mbedtls.c b/components/esp-tls/esp_tls_mbedtls.c new file mode 100644 index 000000000..f2d3480e7 --- /dev/null +++ b/components/esp-tls/esp_tls_mbedtls.c @@ -0,0 +1,547 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// 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. +#include +#include +#include +#include + +#include +#include +#include + +#include +#include "esp_tls_mbedtls.h" +#include "esp_tls_error_capture_internal.h" +#include +#include "esp_log.h" + +static const char *TAG = "esp-tls-mbedtls"; +static mbedtls_x509_crt *global_cacert = NULL; + +typedef struct esp_tls_pki_t { + mbedtls_x509_crt *public_cert; + mbedtls_pk_context *pk_key; + const unsigned char *publiccert_pem_buf; + unsigned int publiccert_pem_bytes; + const unsigned char *privkey_pem_buf; + unsigned int privkey_pem_bytes; + const unsigned char *privkey_password; + unsigned int privkey_password_len; +} esp_tls_pki_t; + +esp_err_t esp_create_mbedtls_handle(const char *hostname, size_t hostlen, const void *cfg, esp_tls_t *tls) +{ + assert(cfg != NULL); + assert(tls != NULL); + int ret; + esp_err_t esp_ret = ESP_FAIL; + tls->server_fd.fd = tls->sockfd; + mbedtls_ssl_init(&tls->ssl); + mbedtls_ctr_drbg_init(&tls->ctr_drbg); + mbedtls_ssl_config_init(&tls->conf); + mbedtls_entropy_init(&tls->entropy); + + if (tls->role == ESP_TLS_CLIENT) { + esp_ret = set_client_config(hostname, hostlen, (esp_tls_cfg_t *)cfg, tls); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to set client configurations"); + goto exit; + } + } else if (tls->role == ESP_TLS_SERVER) { +#ifdef CONFIG_ESP_TLS_SERVER + esp_ret = set_server_config((esp_tls_cfg_server_t *) cfg, tls); + if (esp_ret != 0) { + ESP_LOGE(TAG, "Failed to set server configurations"); + goto exit; + } +#else + ESP_LOGE(TAG, "ESP_TLS_SERVER Not enabled in Kconfig"); + goto exit; +#endif + } + + if ((ret = mbedtls_ctr_drbg_seed(&tls->ctr_drbg, + mbedtls_entropy_func, &tls->entropy, NULL, 0)) != 0) { + ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + esp_ret = ESP_ERR_MBEDTLS_CTR_DRBG_SEED_FAILED; + goto exit; + } + + mbedtls_ssl_conf_rng(&tls->conf, mbedtls_ctr_drbg_random, &tls->ctr_drbg); + +#ifdef CONFIG_MBEDTLS_DEBUG + mbedtls_esp_enable_debug_log(&tls->conf, CONFIG_MBEDTLS_DEBUG_LEVEL); +#endif + + if ((ret = mbedtls_ssl_setup(&tls->ssl, &tls->conf)) != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_setup returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + esp_ret = ESP_ERR_MBEDTLS_SSL_SETUP_FAILED; + goto exit; + } + mbedtls_ssl_set_bio(&tls->ssl, &tls->server_fd, mbedtls_net_send, mbedtls_net_recv, NULL); + + return ESP_OK; + +exit: + esp_mbedtls_cleanup(tls); + return esp_ret; + +} + +int esp_mbedtls_handshake(esp_tls_t *tls, const esp_tls_cfg_t *cfg) +{ + int ret; + ret = mbedtls_ssl_handshake(&tls->ssl); + if (ret == 0) { + tls->conn_state = ESP_TLS_DONE; + return 1; + } else { + if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + ESP_LOGE(TAG, "mbedtls_ssl_handshake returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED); + if (cfg->cacert_buf != NULL || cfg->use_global_ca_store == true) { + /* This is to check whether handshake failed due to invalid certificate*/ + esp_mbedtls_verify_certificate(tls); + } + tls->conn_state = ESP_TLS_FAIL; + return -1; + } + /* Irrespective of blocking or non-blocking I/O, we return on getting MBEDTLS_ERR_SSL_WANT_READ + or MBEDTLS_ERR_SSL_WANT_WRITE during handshake */ + return 0; + } +} + +ssize_t esp_mbedtls_read(esp_tls_t *tls, char *data, size_t datalen) +{ + + ssize_t ret = mbedtls_ssl_read(&tls->ssl, (unsigned char *)data, datalen); + if (ret < 0) { + if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { + return 0; + } + if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + ESP_LOGE(TAG, "read error :%d:", ret); + } + } + return ret; +} + +ssize_t esp_mbedtls_write(esp_tls_t *tls, const char *data, size_t datalen) +{ + size_t written = 0; + size_t write_len = datalen; + while (written < datalen) { + if (write_len > MBEDTLS_SSL_OUT_CONTENT_LEN) { + write_len = MBEDTLS_SSL_OUT_CONTENT_LEN; + } + if (datalen > MBEDTLS_SSL_OUT_CONTENT_LEN) { + ESP_LOGD(TAG, "Fragmenting data of excessive size :%d, offset: %d, size %d", datalen, written, write_len); + } + ssize_t ret = mbedtls_ssl_write(&tls->ssl, (unsigned char*) data + written, write_len); + if (ret <= 0) { + if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != 0) { + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_MBEDTLS_SSL_WRITE_FAILED); + ESP_LOGE(TAG, "write error :%d:", ret); + return ret; + } else { + // Exitting the tls-write process as less than desired datalen are writable + ESP_LOGD(TAG, "mbedtls_ssl_write() returned %d, already written %d, exitting...", ret, written); + return written; + } + } + written += ret; + write_len = datalen - written; + } + return written; +} + +void esp_mbedtls_conn_delete(esp_tls_t *tls) +{ + if (tls != NULL) { + esp_mbedtls_cleanup(tls); + if (tls->is_tls) { + mbedtls_net_free(&tls->server_fd); + } + } +} + +void esp_mbedtls_verify_certificate(esp_tls_t *tls) +{ + int flags; + char buf[100]; + if ((flags = mbedtls_ssl_get_verify_result(&tls->ssl)) != 0) { + ESP_LOGI(TAG, "Failed to verify peer certificate!"); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS_CERT_FLAGS, flags); + bzero(buf, sizeof(buf)); + mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", flags); + ESP_LOGI(TAG, "verification info: %s", buf); + } else { + ESP_LOGI(TAG, "Certificate verified."); + } +} + +ssize_t esp_mbedtls_get_bytes_avail(esp_tls_t *tls) +{ + if (!tls) { + ESP_LOGE(TAG, "empty arg passed to esp_tls_get_bytes_avail()"); + return ESP_FAIL; + } + return mbedtls_ssl_get_bytes_avail(&tls->ssl); +} + +void esp_mbedtls_cleanup(esp_tls_t *tls) +{ + if (!tls) { + return; + } + if (tls->cacert_ptr != global_cacert) { + mbedtls_x509_crt_free(tls->cacert_ptr); + } + tls->cacert_ptr = NULL; +#ifdef CONFIG_ESP_TLS_SERVER + mbedtls_x509_crt_free(&tls->servercert); + mbedtls_pk_free(&tls->serverkey); +#endif + mbedtls_x509_crt_free(&tls->cacert); + mbedtls_x509_crt_free(&tls->clientcert); + mbedtls_pk_free(&tls->clientkey); + mbedtls_entropy_free(&tls->entropy); + mbedtls_ssl_config_free(&tls->conf); + mbedtls_ctr_drbg_free(&tls->ctr_drbg); + mbedtls_ssl_free(&tls->ssl); +} + +static esp_err_t set_ca_cert(esp_tls_t *tls, const unsigned char *cacert, size_t cacert_len) +{ + assert(tls); + tls->cacert_ptr = &tls->cacert; + mbedtls_x509_crt_init(tls->cacert_ptr); + int ret = mbedtls_x509_crt_parse(tls->cacert_ptr, cacert, cacert_len); + if (ret < 0) { + ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED; + } + mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); + mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); + return ESP_OK; +} + +static esp_err_t set_pki_context(esp_tls_t *tls, const esp_tls_pki_t *pki) +{ + assert(tls); + assert(pki); + int ret; + + if (pki->publiccert_pem_buf != NULL && + pki->privkey_pem_buf != NULL && + pki->public_cert != NULL && + pki->pk_key != NULL) { + + mbedtls_x509_crt_init(pki->public_cert); + mbedtls_pk_init(pki->pk_key); + + ret = mbedtls_x509_crt_parse(pki->public_cert, pki->publiccert_pem_buf, pki->publiccert_pem_bytes); + if (ret < 0) { + ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED; + } + + ret = mbedtls_pk_parse_key(pki->pk_key, pki->privkey_pem_buf, pki->privkey_pem_bytes, + NULL, 0); + if (ret < 0) { + ESP_LOGE(TAG, "mbedtls_pk_parse_keyfile returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED; + } + + ret = mbedtls_ssl_conf_own_cert(&tls->conf, pki->public_cert, pki->pk_key); + if (ret < 0) { + ESP_LOGE(TAG, "mbedtls_ssl_conf_own_cert returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED; + } + } else { + return ESP_ERR_INVALID_ARG; + } + return ESP_OK; +} + +static esp_err_t set_global_ca_store(esp_tls_t *tls) +{ + assert(tls); + if (global_cacert == NULL) { + ESP_LOGE(TAG, "global_cacert is NULL"); + return ESP_ERR_INVALID_STATE; + } + tls->cacert_ptr = global_cacert; + mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); + mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); + return ESP_OK; +} + + +#ifdef CONFIG_ESP_TLS_SERVER +esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls) +{ + assert(cfg != NULL); + assert(tls != NULL); + int ret; + esp_err_t esp_ret; + if ((ret = mbedtls_ssl_config_defaults(&tls->conf, + MBEDTLS_SSL_IS_SERVER, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned %d", ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED; + } + +#ifdef CONFIG_MBEDTLS_SSL_ALPN + if (cfg->alpn_protos) { + mbedtls_ssl_conf_alpn_protocols(&tls->conf, cfg->alpn_protos); + } +#endif + + if (cfg->cacert_buf != NULL) { + esp_ret = set_ca_cert(tls, cfg->cacert_buf, cfg->cacert_bytes); + if (esp_ret != ESP_OK) { + return esp_ret; + } + } else { + mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_NONE); + } + + if (cfg->servercert_buf != NULL && cfg->serverkey_buf != NULL) { + esp_tls_pki_t pki = { + .public_cert = &tls->servercert, + .pk_key = &tls->serverkey, + .publiccert_pem_buf = cfg->servercert_buf, + .publiccert_pem_bytes = cfg->servercert_bytes, + .privkey_pem_buf = cfg->serverkey_buf, + .privkey_pem_bytes = cfg->serverkey_bytes, + .privkey_password = cfg->serverkey_password, + .privkey_password_len = cfg->serverkey_password_len, + }; + esp_ret = set_pki_context(tls, &pki); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to set server pki context"); + return esp_ret; + } + } else { + ESP_LOGE(TAG, "Missing server certificate and/or key"); + return ESP_ERR_INVALID_STATE; + } + return ESP_OK; +} +#endif /* ! CONFIG_ESP_TLS_SERVER */ + +esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t *cfg, esp_tls_t *tls) +{ + assert(cfg != NULL); + assert(tls != NULL); + int ret; + if (!cfg->skip_common_name) { + char *use_host = NULL; + if (cfg->common_name != NULL) { + use_host = strndup(cfg->common_name, strlen(cfg->common_name)); + } else { + use_host = strndup(hostname, hostlen); + } + + if (use_host == NULL) { + return ESP_ERR_NO_MEM; + } + /* Hostname set here should match CN in server certificate */ + if ((ret = mbedtls_ssl_set_hostname(&tls->ssl, use_host)) != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_set_hostname returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + free(use_host); + return ESP_ERR_MBEDTLS_SSL_SET_HOSTNAME_FAILED; + } + free(use_host); + } + + if ((ret = mbedtls_ssl_config_defaults(&tls->conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED; + } + +#ifdef CONFIG_MBEDTLS_SSL_ALPN + if (cfg->alpn_protos) { + if ((ret = mbedtls_ssl_conf_alpn_protocols(&tls->conf, cfg->alpn_protos) != 0)) { + ESP_LOGE(TAG, "mbedtls_ssl_conf_alpn_protocols returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_SSL_CONF_ALPN_PROTOCOLS_FAILED; + } + } +#endif + if (cfg->use_global_ca_store == true) { + esp_err_t esp_ret = set_global_ca_store(tls); + if (esp_ret != ESP_OK) { + return esp_ret; + } + } else if (cfg->cacert_buf != NULL) { + esp_err_t esp_ret = set_ca_cert(tls, cfg->cacert_buf, cfg->cacert_bytes); + if (esp_ret != ESP_OK) { + return esp_ret; + } + mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); + } else if (cfg->psk_hint_key) { +#if defined(CONFIG_ESP_TLS_PSK_VERIFICATION) + // + // PSK encryption mode is configured only if no certificate supplied and psk pointer not null + ESP_LOGD(TAG, "ssl psk authentication"); + ret = mbedtls_ssl_conf_psk(&tls->conf, cfg->psk_hint_key->key, cfg->psk_hint_key->key_size, + (const unsigned char *)cfg->psk_hint_key->hint, strlen(cfg->psk_hint_key->hint)); + if (ret != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_conf_psk returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_SSL_CONF_PSK_FAILED; + } +#else + ESP_LOGE(TAG, "psk_hint_key configured but not enabled in menuconfig: Please enable ESP_TLS_PSK_VERIFICATION option"); + return ESP_ERR_INVALID_STATE; +#endif + } else { + mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_NONE); + } + + if (cfg->clientcert_buf != NULL && cfg->clientkey_buf != NULL) { + esp_tls_pki_t pki = { + .public_cert = &tls->clientcert, + .pk_key = &tls->clientkey, + .publiccert_pem_buf = cfg->clientcert_buf, + .publiccert_pem_bytes = cfg->clientcert_bytes, + .privkey_pem_buf = cfg->clientkey_buf, + .privkey_pem_bytes = cfg->clientkey_bytes, + .privkey_password = cfg->clientkey_password, + .privkey_password_len = cfg->clientkey_password_len, + }; + esp_err_t esp_ret = set_pki_context(tls, &pki); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to set client pki context"); + return esp_ret; + } + } else if (cfg->clientcert_buf != NULL || cfg->clientkey_buf != NULL) { + ESP_LOGE(TAG, "You have to provide both clientcert_buf and clientkey_buf for mutual authentication"); + return ESP_ERR_INVALID_STATE; + } + return ESP_OK; +} + +#ifdef CONFIG_ESP_TLS_SERVER +/** + * @brief Create TLS/SSL server session + */ +int esp_mbedtls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp_tls_t *tls) +{ + if (tls == NULL || cfg == NULL) { + return -1; + } + tls->role = ESP_TLS_SERVER; + tls->sockfd = sockfd; + esp_err_t esp_ret = esp_create_mbedtls_handle(NULL, 0, cfg, tls); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "create_ssl_handle failed"); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, esp_ret); + tls->conn_state = ESP_TLS_FAIL; + return -1; + } + tls->read = esp_mbedtls_read; + tls->write = esp_mbedtls_write; + int ret; + while ((ret = mbedtls_ssl_handshake(&tls->ssl)) != 0) { + if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + ESP_LOGE(TAG, "mbedtls_ssl_handshake returned %d", ret); + tls->conn_state = ESP_TLS_FAIL; + return ret; + } + } + return 0; +} +/** + * @brief Close the server side TLS/SSL connection and free any allocated resources. + */ +void esp_mbedtls_server_session_delete(esp_tls_t *tls) +{ + if (tls != NULL) { + esp_mbedtls_cleanup(tls); + free(tls); + } +}; +#endif /* ! CONFIG_ESP_TLS_SERVER */ + +esp_err_t esp_mbedtls_init_global_ca_store(void) +{ + if (global_cacert == NULL) { + global_cacert = (mbedtls_x509_crt *)calloc(1, sizeof(mbedtls_x509_crt)); + if (global_cacert == NULL) { + ESP_LOGE(TAG, "global_cacert not allocated"); + return ESP_ERR_NO_MEM; + } + mbedtls_x509_crt_init(global_cacert); + } + return ESP_OK; +} + +esp_err_t esp_mbedtls_set_global_ca_store(const unsigned char *cacert_pem_buf, const unsigned int cacert_pem_bytes) +{ + if (cacert_pem_buf == NULL) { + ESP_LOGE(TAG, "cacert_pem_buf is null"); + return ESP_ERR_INVALID_ARG; + } + int ret; + if (global_cacert == NULL) { + ret = esp_mbedtls_init_global_ca_store(); + if (ret != ESP_OK) { + return ret; + } + } + ret = mbedtls_x509_crt_parse(global_cacert, cacert_pem_buf, cacert_pem_bytes); + if (ret < 0) { + ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x", -ret); + mbedtls_x509_crt_free(global_cacert); + global_cacert = NULL; + return ESP_FAIL; + } else if (ret > 0) { + ESP_LOGE(TAG, "mbedtls_x509_crt_parse was partly successful. No. of failed certificates: %d", ret); + return ESP_ERR_MBEDTLS_CERT_PARTLY_OK; + } + return ESP_OK; +} + +mbedtls_x509_crt *esp_mbedtls_get_global_ca_store(void) +{ + return global_cacert; +} + +void esp_mbedtls_free_global_ca_store(void) +{ + if (global_cacert) { + mbedtls_x509_crt_free(global_cacert); + global_cacert = NULL; + } +} diff --git a/components/esp-tls/esp_tls_wolfssl.c b/components/esp-tls/esp_tls_wolfssl.c new file mode 100644 index 000000000..1caa0b31f --- /dev/null +++ b/components/esp-tls/esp_tls_wolfssl.c @@ -0,0 +1,244 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// 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. + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include "esp_tls_wolfssl.h" +#include "esp_tls_error_capture_internal.h" +#include +#include "esp_log.h" + +static unsigned char *global_cacert = NULL; +static unsigned int global_cacert_pem_bytes = 0; +static const char *TAG = "esp-tls-wolfssl"; + +int esp_create_wolfssl_handle(const char *hostname, size_t hostlen, const void *cfg1, esp_tls_t *tls) +{ +#ifdef CONFIG_ESP_DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); +#endif + const esp_tls_cfg_t *cfg = cfg1; + assert(cfg != NULL); + assert(tls != NULL); + + int ret; + ret = wolfSSL_Init(); + if (ret != WOLFSSL_SUCCESS) { + ESP_LOGE(TAG, "Init wolfSSL failed: %d", ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + goto exit; + } + + tls->priv_ctx = (void *)wolfSSL_CTX_new(wolfTLSv1_2_client_method()); + if (!tls->priv_ctx) { + ESP_LOGE(TAG, "Set wolfSSL ctx failed"); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + goto exit; + } + +#ifdef HAVE_ALPN + if (cfg->alpn_protos) { + char **alpn_list = (char **)cfg->alpn_protos; + for (; *alpn_list != NULL; alpn_list ++) { + if (wolfSSL_UseALPN( (WOLFSSL *)tls->priv_ssl, *alpn_list, strlen(*alpn_list), WOLFSSL_ALPN_FAILED_ON_MISMATCH) != WOLFSSL_SUCCESS) { + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + ESP_LOGE(TAG, "Use wolfSSL ALPN failed"); + goto exit; + } + } + } +#endif + + if ( cfg->use_global_ca_store == true) { + wolfSSL_CTX_load_verify_buffer( (WOLFSSL_CTX *)tls->priv_ctx, global_cacert, global_cacert_pem_bytes, WOLFSSL_FILETYPE_PEM); + wolfSSL_CTX_set_verify( (WOLFSSL_CTX *)tls->priv_ctx, SSL_VERIFY_PEER, NULL); + } else if (cfg->cacert_pem_buf != NULL) { + wolfSSL_CTX_load_verify_buffer( (WOLFSSL_CTX *)tls->priv_ctx, cfg->cacert_pem_buf, cfg->cacert_pem_bytes, WOLFSSL_FILETYPE_PEM); + wolfSSL_CTX_set_verify( (WOLFSSL_CTX *)tls->priv_ctx, SSL_VERIFY_PEER, NULL); + } else if (cfg->psk_hint_key) { + ESP_LOGE(TAG,"psk_hint_key not supported in wolfssl"); + goto exit; + } else { + wolfSSL_CTX_set_verify( (WOLFSSL_CTX *)tls->priv_ctx, SSL_VERIFY_NONE, NULL); + } + + if (cfg->clientcert_pem_buf != NULL && cfg->clientkey_pem_buf != NULL) { + wolfSSL_CTX_use_certificate_buffer( (WOLFSSL_CTX *)tls->priv_ctx, cfg->clientcert_pem_buf, cfg->clientcert_pem_bytes, WOLFSSL_FILETYPE_PEM); + wolfSSL_CTX_use_PrivateKey_buffer( (WOLFSSL_CTX *)tls->priv_ctx, cfg->clientkey_pem_buf, cfg->clientkey_pem_bytes, WOLFSSL_FILETYPE_PEM); + } else if (cfg->clientcert_pem_buf != NULL || cfg->clientkey_pem_buf != NULL) { + ESP_LOGE(TAG, "You have to provide both clientcert_pem_buf and clientkey_pem_buf for mutual authentication\n\n"); + goto exit; + } + + tls->priv_ssl =(void *)wolfSSL_new( (WOLFSSL_CTX *)tls->priv_ctx); + if (!tls->priv_ssl) { + ESP_LOGE(TAG, "Create wolfSSL failed"); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + goto exit; + } + +#ifdef HAVE_SNI + /* Hostname set here should match CN in server certificate */ + char *use_host = strndup(hostname, hostlen); + if (!use_host) { + goto exit; + } + wolfSSL_set_tlsext_host_name( (WOLFSSL *)tls->priv_ssl, use_host); + free(use_host); +#endif + + wolfSSL_set_fd((WOLFSSL *)tls->priv_ssl, tls->sockfd); + return 0; +exit: + esp_wolfssl_cleanup(tls); + return ret; +} + +int esp_wolfssl_handshake(esp_tls_t *tls, const esp_tls_cfg_t *cfg) +{ + int ret; + ret = wolfSSL_connect( (WOLFSSL *)tls->priv_ssl); + if (ret == WOLFSSL_SUCCESS) { + tls->conn_state = ESP_TLS_DONE; + return 1; + } else { + int err = wolfSSL_get_error( (WOLFSSL *)tls->priv_ssl, ret); + if (err != WOLFSSL_ERROR_WANT_READ && err != WOLFSSL_ERROR_WANT_WRITE) { + ESP_LOGE(TAG, "wolfSSL_connect returned -0x%x", -ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + + if (cfg->cacert_pem_buf != NULL || cfg->use_global_ca_store == true) { + /* This is to check whether handshake failed due to invalid certificate*/ + esp_wolfssl_verify_certificate(tls); + } + tls->conn_state = ESP_TLS_FAIL; + return -1; + } + /* Irrespective of blocking or non-blocking I/O, we return on getting wolfSSL_want_read + or wolfSSL_want_write during handshake */ + return 0; + } +} + +ssize_t esp_wolfssl_read(esp_tls_t *tls, char *data, size_t datalen) +{ + ssize_t ret = wolfSSL_read( (WOLFSSL *)tls->priv_ssl, (unsigned char *)data, datalen); + if (ret < 0) { + ret = wolfSSL_get_error( (WOLFSSL *)tls->priv_ssl, ret); + /* peer sent close notify */ + if (ret == WOLFSSL_ERROR_ZERO_RETURN) { + return 0; + } + + if (ret != WOLFSSL_ERROR_WANT_READ && ret != WOLFSSL_ERROR_WANT_WRITE) { + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + ESP_LOGE(TAG, "read error :%d:", ret); + } + } + return ret; +} + +ssize_t esp_wolfssl_write(esp_tls_t *tls, const char *data, size_t datalen) +{ + ssize_t ret = wolfSSL_write( (WOLFSSL *)tls->priv_ssl, (unsigned char *) data, datalen); + if (ret < 0) { + ret = wolfSSL_get_error( (WOLFSSL *)tls->priv_ssl, ret); + if (ret != WOLFSSL_ERROR_WANT_READ && ret != WOLFSSL_ERROR_WANT_WRITE) { + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); + ESP_LOGE(TAG, "write error :%d:", ret); + } + } + return ret; +} + +void esp_wolfssl_verify_certificate(esp_tls_t *tls) +{ + int flags; + if ((flags = wolfSSL_get_verify_result( (WOLFSSL *)tls->priv_ssl)) != WOLFSSL_SUCCESS) { + ESP_LOGE(TAG, "Failed to verify peer certificate %d!", flags); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL_CERT_FLAGS, flags); + } else { + ESP_LOGI(TAG, "Certificate verified."); + } +} + +ssize_t esp_wolfssl_get_bytes_avail(esp_tls_t *tls) +{ + if (!tls) { + ESP_LOGE(TAG, "empty arg passed to esp_tls_get_bytes_avail()"); + return ESP_FAIL; + } + return wolfSSL_pending( (WOLFSSL *)tls->priv_ssl); +} + +void esp_wolfssl_conn_delete(esp_tls_t *tls) +{ + if (tls != NULL) { + esp_wolfssl_cleanup(tls); + } +} + +void esp_wolfssl_cleanup(esp_tls_t *tls) +{ + if (!tls) { + return; + } + wolfSSL_shutdown( (WOLFSSL *)tls->priv_ssl); + wolfSSL_free( (WOLFSSL *)tls->priv_ssl); + wolfSSL_CTX_free( (WOLFSSL_CTX *)tls->priv_ctx); + wolfSSL_Cleanup(); +} + +esp_err_t esp_wolfssl_init_global_ca_store(void) +{ + /* This function is just to provide consistancy between function calls of esp_tls.h and wolfssl */ + return ESP_OK; +} + +esp_err_t esp_wolfssl_set_global_ca_store(const unsigned char *cacert_pem_buf, const unsigned int cacert_pem_bytes) +{ + if (cacert_pem_buf == NULL) { + ESP_LOGE(TAG, "cacert_pem_buf is null"); + return ESP_ERR_INVALID_ARG; + } + if (global_cacert != NULL) { + esp_wolfssl_free_global_ca_store(); + } + + global_cacert = (unsigned char *)strndup((const char *)cacert_pem_buf, cacert_pem_bytes); + if (!global_cacert) { + return ESP_FAIL; + } + + global_cacert_pem_bytes = cacert_pem_bytes; + + return ESP_OK; +} + +void esp_wolfssl_free_global_ca_store(void) +{ + if (global_cacert) { + free(global_cacert); + global_cacert = NULL; + global_cacert_pem_bytes = 0; + } +} diff --git a/components/esp-tls/private_include/esp_tls_error_capture_internal.h b/components/esp-tls/private_include/esp_tls_error_capture_internal.h index 89ee4435c..d047b543b 100644 --- a/components/esp-tls/private_include/esp_tls_error_capture_internal.h +++ b/components/esp-tls/private_include/esp_tls_error_capture_internal.h @@ -33,11 +33,13 @@ typedef enum { ERR_TYPE_MBEDTLS, ERR_TYPE_MBEDTLS_CERT_FLAGS, ERR_TYPE_ESP, + ERR_TYPE_WOLFSSL, + ERR_TYPE_WOLFSSL_CERT_FLAGS, } err_type_t; /** * Error tracker logging macro, this implementation saves latest errors of - * ERR_TYPE_ESP, ERR_TYPE_MBEDTLS and ERR_TYPE_MBEDTLS_CERT_FLAGS types + * ERR_TYPE_ESP, ERR_TYPE_ESP_TLS and ERR_TYPE_ESP_TLS_CERT_FLAGS types */ #define ESP_INT_EVENT_TRACKER_CAPTURE(h, type, code) esp_int_event_tracker_capture(h, type, code) @@ -47,13 +49,19 @@ static inline void esp_int_event_tracker_capture(esp_tls_error_handle_t h, uint3 if (type == ERR_TYPE_ESP) { h->last_error = code; } else if (type == ERR_TYPE_MBEDTLS) { - h->mbedtls_error_code = code; + h->esp_tls_error_code = code; } else if (type == ERR_TYPE_MBEDTLS_CERT_FLAGS) { - h->mbedtls_flags = code; + h->esp_tls_flags = code; + } else if (type == ERR_TYPE_WOLFSSL) { + h->esp_tls_error_code = code; + } else if (type == ERR_TYPE_WOLFSSL_CERT_FLAGS) { + h->esp_tls_flags = code; } } } + + #ifdef __cplusplus } #endif diff --git a/components/esp-tls/private_include/esp_tls_mbedtls.h b/components/esp-tls/private_include/esp_tls_mbedtls.h new file mode 100644 index 000000000..362a71fd6 --- /dev/null +++ b/components/esp-tls/private_include/esp_tls_mbedtls.h @@ -0,0 +1,104 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// 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 "esp_tls.h" + +/** + * Internal Callback API for mbedtls_ssl_read + */ +ssize_t esp_mbedtls_read(esp_tls_t *tls, char *data, size_t datalen); + +/** + * Internal callback API for mbedtls_ssl_write + */ +ssize_t esp_mbedtls_write(esp_tls_t *tls, const char *data, size_t datalen); + +/** + * Internal Callback for mbedtls_handshake + */ +int esp_mbedtls_handshake(esp_tls_t *tls, const esp_tls_cfg_t *cfg); + +/** + * Internal Callback for mbedtls_cleanup , frees up all the memory used by mbedtls + */ +void esp_mbedtls_cleanup(esp_tls_t *tls); + +/** + * Internal Callback for Certificate verification for mbedtls + */ +void esp_mbedtls_verify_certificate(esp_tls_t *tls); + +/** + * Internal Callback for deleting the mbedtls connection + */ +void esp_mbedtls_conn_delete(esp_tls_t *tls); + +/** + * Internal Callback for mbedtls_get_bytes_avail + */ +ssize_t esp_mbedtls_get_bytes_avail(esp_tls_t *tls); + +/** + * Internal Callback for creating ssl handle for mbedtls + */ +esp_err_t esp_create_mbedtls_handle(const char *hostname, size_t hostlen, const void *cfg, esp_tls_t *tls); + +#ifdef CONFIG_ESP_TLS_SERVER +/** + * Internal Callback for set_server_config + * + * /note :- can only be used with mbedtls ssl library + */ +esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls); + +/** + * Internal Callback for mbedtls_server_session_create + * + * /note :- The function can only be used with mbedtls ssl library + */ +int esp_mbedtls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp_tls_t *tls); + +/** + * Internal Callback for mbedtls_server_session_delete + * + * /note :- The function can only be used with mbedtls ssl library + */ +void esp_mbedtls_server_session_delete(esp_tls_t *tls); +#endif + +/** + * Internal Callback for set_client_config_function + */ +esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t *cfg, esp_tls_t *tls); + +/** + * Internal Callback for mbedtls_init_global_ca_store + */ +esp_err_t esp_mbedtls_init_global_ca_store(void); + +/** + * Callback function for setting global CA store data for TLS/SSL using mbedtls + */ +esp_err_t esp_mbedtls_set_global_ca_store(const unsigned char *cacert_pem_buf, const unsigned int cacert_pem_bytes); + +/** + * Internal Callback for esp_tls_global_ca_store + */ +mbedtls_x509_crt *esp_mbedtls_get_global_ca_store(void); + +/** + * Callback function for freeing global ca store for TLS/SSL using mbedtls + */ +void esp_mbedtls_free_global_ca_store(void); diff --git a/components/esp-tls/private_include/esp_tls_wolfssl.h b/components/esp-tls/private_include/esp_tls_wolfssl.h new file mode 100644 index 000000000..73cb9f2f9 --- /dev/null +++ b/components/esp-tls/private_include/esp_tls_wolfssl.h @@ -0,0 +1,72 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// 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 "esp_tls.h" + +/** + * Internal Callback for creating ssl handle for wolfssl + */ +int esp_create_wolfssl_handle(const char *hostname, size_t hostlen, const void *cfg, esp_tls_t *tls); + +/** + * Internal Callback for wolfssl_handshake + */ +int esp_wolfssl_handshake(esp_tls_t *tls, const esp_tls_cfg_t *cfg); + +/** + * Internal Callback API for wolfssl_ssl_read + */ +ssize_t esp_wolfssl_read(esp_tls_t *tls, char *data, size_t datalen); + +/** + * Internal callback API for wolfssl_ssl_write + */ +ssize_t esp_wolfssl_write(esp_tls_t *tls, const char *data, size_t datalen); + +/** + * Internal Callback for wolfssl_cleanup , frees up all the memory used by wolfssl + */ +void esp_wolfssl_cleanup(esp_tls_t *tls); + +/** + * Internal Callback for Certificate verification for wolfssl + */ +void esp_wolfssl_verify_certificate(esp_tls_t *tls); + +/** + * Internal Callback for deleting the wolfssl connection + */ +void esp_wolfssl_conn_delete(esp_tls_t *tls); + +/** + * Internal Callback for wolfssl_get_bytes_avail + */ +ssize_t esp_wolfssl_get_bytes_avail(esp_tls_t *tls); + +/** + * Callback function for setting global CA store data for TLS/SSL using wolfssl + */ +esp_err_t esp_wolfssl_set_global_ca_store(const unsigned char *cacert_pem_buf, const unsigned int cacert_pem_bytes); + +/** + * Callback function for freeing global ca store for TLS/SSL using wolfssl + */ +void esp_wolfssl_free_global_ca_store(void); + +/** + * + * Callback function for Initializing the global ca store for TLS?SSL using wolfssl + */ +esp_err_t esp_wolfssl_init_global_ca_store(void); diff --git a/docs/en/api-reference/protocols/esp_tls.rst b/docs/en/api-reference/protocols/esp_tls.rst index 1552d7dab..24e5bf160 100644 --- a/docs/en/api-reference/protocols/esp_tls.rst +++ b/docs/en/api-reference/protocols/esp_tls.rst @@ -6,10 +6,13 @@ Overview The ESP-TLS component provides a simplified API interface for accessing the commonly used TLS functionality. It supports common scenarios like CA certification validation, SNI, ALPN negotiation, non-blocking connection among others. -All the configuration can be specified in the esp_tls_cfg_t data structure. Once done, TLS communication can be conducted using the following APIs: -* esp_tls_conn_new(): for opening a new TLS connection -* esp_tls_conn_read/write(): for reading/writing from the connection -* esp_tls_conn_delete(): for freeing up the connection +All the configuration can be specified in the ``esp_tls_cfg_t`` data structure. Once done, TLS communication can be conducted using the following APIs: + + * :cpp:func:`esp_tls_conn_new`: for opening a new TLS connection. + * :cpp:func:`esp_tls_conn_read`: for reading from the connection. + * :cpp:func:`esp_tls_conn_write`: for writing into the connection. + * :cpp:func:`esp_tls_conn_delete`: for freeing up the connection. + Any application layer protocol like HTTP1, HTTP2 etc can be executed on top of this layer. Application Example @@ -17,8 +20,75 @@ Application Example Simple HTTPS example that uses ESP-TLS to establish a secure socket connection: :example:`protocols/https_request`. +Tree structure for ESP-TLS component +------------------------------------- + .. highlight:: none + + :: + + ├── esp_tls.c + ├── esp_tls.h + ├── esp_tls_mbedtls.c + ├── esp_tls_wolfssl.c + └── private_include + ├── esp_tls_mbedtls.h + └── esp_tls_wolfssl.h + +The ESP-TLS component has a file :component_file:`esp-tls/esp_tls.h` which contain the public API headers for the component. Internally ESP-TLS component uses one +of the two SSL/TLS Libraries between mbedtls and wolfssl for its operation. API specific to mbedtls are present in :component_file:`esp-tls/private_include/esp_tls_mbedtls.h` and API +specific to wolfssl are present in :component_file:`esp-tls/private_include/esp_tls_wolfssl.h`. + +Underlying SSL/TLS Library Options +---------------------------------- +The ESP-TLS component has an option to use mbedtls or wolfssl as their underlying SSL/TLS library. By default only mbedtls is available and is +used, wolfssl SSL/TLS library is available publicly at https://github.com/espressif/esp-wolfssl. The repository provides wolfssl component in binary format, it +also provides few examples which are useful for understanding the API. Please refer the repository README.md for +information on licensing and other options. Please see below option for using wolfssl in your project. + +.. note:: `As the library options are internal to ESP-TLS, switching the libries will not change ESP-TLS specific code for a project.` + +How to use wolfssl with ESP-IDF +------------------------------- +There are two ways to use wolfssl in your project + +1) Directly add wolfssl as a component in your project with following three commands.:: + + (First change directory (cd) to your project directory) + mkdir components + cd components + git clone https://github.com/espressif/esp-wolfssl.git + +2) Add wolfssl as an extra component in your project. + +* Download wolfssl with:: + + git clone https://github.com/espressif/esp-wolfssl.git + +* Include esp-wolfssl in ESP-IDF with setting EXTRA_COMPONENT_DIRS in CMakeLists.txt/Makefile of your project as done in `wolfssl/examples `_. For reference see Optional Project variables in :doc:`build-system.` + +After above steps, you will have option to choose wolfssl as underlying SSL/TLS library in configuration menu of your project as follows:: + + idf.py/make menuconfig -> ESP-TLS -> choose SSL/TLS Library -> mbedtls/wolfssl + +Comparison between mbedtls and wolfssl +-------------------------------------- +The following table shows a typical comparison between wolfssl and mbedtls when :example:`protocols/https_request` example `(which has server authentication)` was run with both +SSL/TLS libraries and with all respective configurations set to default. +`(mbedtls IN_CONTENT length and OUT_CONTENT length were set to 16384 bytes and 4096 bytes respectively)` + + +---------------------+------------+-----------+ + | Property | Wolfssl | Mbedtls | + +=====================+============+===========+ + | Total Heap Consumed | ~19 Kb | ~37 Kb | + +---------------------+------------+-----------+ + | Task Stack Used | ~2.2 Kb | ~3.6 Kb | + +---------------------+------------+-----------+ + | Bin size | ~858 Kb | ~736 Kb | + +---------------------+------------+-----------+ + +.. note:: `These values are subject to change with change in configuration options and version of respective libraries`. + API Reference ------------- .. include:: /_build/inc/esp_tls.inc - From 988f0c8feb7ed9082d549c875a712b9c182eff8a Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Tue, 17 Sep 2019 17:11:02 +0530 Subject: [PATCH 2/2] ESP_TLS: Generalizing error messages for esp_tls :Replace mbedtls specific error messages --- components/esp-tls/esp_tls.h | 9 +++++++++ components/esp-tls/esp_tls_mbedtls.c | 12 ++++++------ components/esp-tls/esp_tls_wolfssl.c | 6 +++--- .../http2_request/components/sh2lib/sh2lib.c | 5 ++--- .../https_request/main/https_request_example_main.c | 4 ++-- 5 files changed, 22 insertions(+), 14 deletions(-) diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h index c92d8cdf8..d12f210d6 100644 --- a/components/esp-tls/esp_tls.h +++ b/components/esp-tls/esp_tls.h @@ -55,6 +55,15 @@ extern "C" { #define ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x10) /*!< mbedtls api returned failed */ #define ESP_ERR_MBEDTLS_SSL_CONF_PSK_FAILED (ESP_ERR_ESP_TLS_BASE + 0x11) /*!< mbedtls api returned failed */ +#ifdef CONFIG_ESP_TLS_USING_MBEDTLS +#define ESP_TLS_ERR_SSL_WANT_READ MBEDTLS_ERR_SSL_WANT_READ +#define ESP_TLS_ERR_SSL_WANT_WRITE MBEDTLS_ERR_SSL_WANT_WRITE +#define ESP_TLS_ERR_SSL_TIMEOUT MBEDTLS_ERR_SSL_TIMEOUT +#elif CONFIG_ESP_TLS_USING_WOLFSSL /* CONFIG_ESP_TLS_USING_MBEDTLS */ +#define ESP_TLS_ERR_SSL_WANT_READ WOLFSSL_ERROR_WANT_READ +#define ESP_TLS_ERR_SSL_WANT_WRITE WOLFSSL_ERROR_WANT_WRITE +#define ESP_TLS_ERR_SSL_TIMEOUT WOLFSSL_CBIO_ERR_TIMEOUT +#endif /*CONFIG_ESP_TLS_USING_WOLFSSL */ typedef struct esp_tls_last_error* esp_tls_error_handle_t; /** diff --git a/components/esp-tls/esp_tls_mbedtls.c b/components/esp-tls/esp_tls_mbedtls.c index f2d3480e7..823fa6dbf 100644 --- a/components/esp-tls/esp_tls_mbedtls.c +++ b/components/esp-tls/esp_tls_mbedtls.c @@ -109,7 +109,7 @@ int esp_mbedtls_handshake(esp_tls_t *tls, const esp_tls_cfg_t *cfg) tls->conn_state = ESP_TLS_DONE; return 1; } else { - if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) { ESP_LOGE(TAG, "mbedtls_ssl_handshake returned -0x%x", -ret); ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED); @@ -120,8 +120,8 @@ int esp_mbedtls_handshake(esp_tls_t *tls, const esp_tls_cfg_t *cfg) tls->conn_state = ESP_TLS_FAIL; return -1; } - /* Irrespective of blocking or non-blocking I/O, we return on getting MBEDTLS_ERR_SSL_WANT_READ - or MBEDTLS_ERR_SSL_WANT_WRITE during handshake */ + /* Irrespective of blocking or non-blocking I/O, we return on getting ESP_TLS_ERR_SSL_WANT_READ + or ESP_TLS_ERR_SSL_WANT_WRITE during handshake */ return 0; } } @@ -134,7 +134,7 @@ ssize_t esp_mbedtls_read(esp_tls_t *tls, char *data, size_t datalen) if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { return 0; } - if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) { ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); ESP_LOGE(TAG, "read error :%d:", ret); } @@ -155,7 +155,7 @@ ssize_t esp_mbedtls_write(esp_tls_t *tls, const char *data, size_t datalen) } ssize_t ret = mbedtls_ssl_write(&tls->ssl, (unsigned char*) data + written, write_len); if (ret <= 0) { - if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != 0) { + if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE && ret != 0) { ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret); ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_MBEDTLS_SSL_WRITE_FAILED); ESP_LOGE(TAG, "write error :%d:", ret); @@ -474,7 +474,7 @@ int esp_mbedtls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp tls->write = esp_mbedtls_write; int ret; while ((ret = mbedtls_ssl_handshake(&tls->ssl)) != 0) { - if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) { ESP_LOGE(TAG, "mbedtls_ssl_handshake returned %d", ret); tls->conn_state = ESP_TLS_FAIL; return ret; diff --git a/components/esp-tls/esp_tls_wolfssl.c b/components/esp-tls/esp_tls_wolfssl.c index 1caa0b31f..351ae0713 100644 --- a/components/esp-tls/esp_tls_wolfssl.c +++ b/components/esp-tls/esp_tls_wolfssl.c @@ -122,7 +122,7 @@ int esp_wolfssl_handshake(esp_tls_t *tls, const esp_tls_cfg_t *cfg) return 1; } else { int err = wolfSSL_get_error( (WOLFSSL *)tls->priv_ssl, ret); - if (err != WOLFSSL_ERROR_WANT_READ && err != WOLFSSL_ERROR_WANT_WRITE) { + if (err != ESP_TLS_ERR_SSL_WANT_READ && err != ESP_TLS_ERR_SSL_WANT_WRITE) { ESP_LOGE(TAG, "wolfSSL_connect returned -0x%x", -ret); ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); @@ -149,7 +149,7 @@ ssize_t esp_wolfssl_read(esp_tls_t *tls, char *data, size_t datalen) return 0; } - if (ret != WOLFSSL_ERROR_WANT_READ && ret != WOLFSSL_ERROR_WANT_WRITE) { + if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) { ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); ESP_LOGE(TAG, "read error :%d:", ret); } @@ -162,7 +162,7 @@ ssize_t esp_wolfssl_write(esp_tls_t *tls, const char *data, size_t datalen) ssize_t ret = wolfSSL_write( (WOLFSSL *)tls->priv_ssl, (unsigned char *) data, datalen); if (ret < 0) { ret = wolfSSL_get_error( (WOLFSSL *)tls->priv_ssl, ret); - if (ret != WOLFSSL_ERROR_WANT_READ && ret != WOLFSSL_ERROR_WANT_WRITE) { + if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) { ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret); ESP_LOGE(TAG, "write error :%d:", ret); } diff --git a/examples/protocols/http2_request/components/sh2lib/sh2lib.c b/examples/protocols/http2_request/components/sh2lib/sh2lib.c index 4447a1280..1b9e89a0e 100644 --- a/examples/protocols/http2_request/components/sh2lib/sh2lib.c +++ b/examples/protocols/http2_request/components/sh2lib/sh2lib.c @@ -39,7 +39,7 @@ static ssize_t callback_send_inner(struct sh2lib_handle *hd, const uint8_t *data { int rv = esp_tls_conn_write(hd->http2_tls, data, length); if (rv <= 0) { - if (rv == MBEDTLS_ERR_SSL_WANT_READ || rv == MBEDTLS_ERR_SSL_WANT_WRITE) { + if (rv == ESP_TLS_ERR_SSL_WANT_READ || rv == ESP_TLS_ERR_SSL_WANT_WRITE) { rv = NGHTTP2_ERR_WOULDBLOCK; } else { rv = NGHTTP2_ERR_CALLBACK_FAILURE; @@ -88,7 +88,7 @@ static ssize_t callback_recv(nghttp2_session *session, uint8_t *buf, int rv; rv = esp_tls_conn_read(hd->http2_tls, (char *)buf, (int)length); if (rv < 0) { - if (rv == MBEDTLS_ERR_SSL_WANT_READ || rv == MBEDTLS_ERR_SSL_WANT_WRITE) { + if (rv == ESP_TLS_ERR_SSL_WANT_READ || rv == ESP_TLS_ERR_SSL_WANT_WRITE) { rv = NGHTTP2_ERR_WOULDBLOCK; } else { rv = NGHTTP2_ERR_CALLBACK_FAILURE; @@ -366,4 +366,3 @@ int sh2lib_do_put(struct sh2lib_handle *hd, const char *path, }; return sh2lib_do_putpost_with_nv(hd, nva, sizeof(nva) / sizeof(nva[0]), send_cb, recv_cb); } - diff --git a/examples/protocols/https_request/main/https_request_example_main.c b/examples/protocols/https_request/main/https_request_example_main.c index 7db142f90..3b986f6bd 100644 --- a/examples/protocols/https_request/main/https_request_example_main.c +++ b/examples/protocols/https_request/main/https_request_example_main.c @@ -96,7 +96,7 @@ static void https_get_task(void *pvParameters) if (ret >= 0) { ESP_LOGI(TAG, "%d bytes written", ret); written_bytes += ret; - } else if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + } else if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) { ESP_LOGE(TAG, "esp_tls_conn_write returned 0x%x", ret); goto exit; } @@ -110,7 +110,7 @@ static void https_get_task(void *pvParameters) bzero(buf, sizeof(buf)); ret = esp_tls_conn_read(tls, (char *)buf, len); - if(ret == MBEDTLS_ERR_SSL_WANT_WRITE || ret == MBEDTLS_ERR_SSL_WANT_READ) + if(ret == ESP_TLS_ERR_SSL_WANT_WRITE || ret == ESP_TLS_ERR_SSL_WANT_READ) continue; if(ret < 0)