diff --git a/components/esp-tls/component.mk b/components/esp-tls/component.mk index 680168b7..52aa5d7e 100644 --- a/components/esp-tls/component.mk +++ b/components/esp-tls/component.mk @@ -1,7 +1,12 @@ -ifdef CONFIG_SSL_USING_MBEDTLS -COMPONENT_SRCDIRS := . -COMPONENT_ADD_INCLUDEDIRS := . -else COMPONENT_SRCDIRS := COMPONENT_ADD_INCLUDEDIRS := + +ifdef CONFIG_SSL_USING_MBEDTLS +COMPONENT_SRCDIRS := . +COMPONENT_ADD_INCLUDEDIRS := . endif + +ifdef CONFIG_SSL_USING_WOLFSSL +COMPONENT_SRCDIRS := . +COMPONENT_ADD_INCLUDEDIRS := . +endif \ No newline at end of file diff --git a/components/esp-tls/esp_tls.c b/components/esp-tls/esp_tls.c index b97f4ebc..039dc31a 100644 --- a/components/esp-tls/esp_tls.c +++ b/components/esp-tls/esp_tls.c @@ -28,7 +28,12 @@ #endif static const char *TAG = "esp-tls"; +#if CONFIG_SSL_USING_MBEDTLS static mbedtls_x509_crt *global_cacert = NULL; +#else +static unsigned char *global_cacert = NULL; +static unsigned int global_cacert_pem_bytes = 0; +#endif #ifdef ESP_PLATFORM #include @@ -67,6 +72,7 @@ static ssize_t tcp_read(esp_tls_t *tls, char *data, size_t datalen) static ssize_t tls_read(esp_tls_t *tls, char *data, size_t datalen) { +#if CONFIG_SSL_USING_MBEDTLS ssize_t ret = mbedtls_ssl_read(&tls->ssl, (unsigned char *)data, datalen); if (ret < 0) { if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { @@ -76,6 +82,20 @@ static ssize_t tls_read(esp_tls_t *tls, char *data, size_t datalen) ESP_LOGE(TAG, "read error :%d:", ret); } } +#else + size_t ret = wolfSSL_read(tls->ssl, (unsigned char *)data, datalen); + if (ret < 0) { + ret = wolfSSL_get_error(tls->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_LOGE(TAG, "read error :%d:", ret); + } + } +#endif return ret; } @@ -146,12 +166,14 @@ err_freeaddr: return ret; } + esp_err_t esp_tls_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 CONFIG_SSL_USING_MBEDTLS if (global_cacert != NULL) { mbedtls_x509_crt_free(global_cacert); } @@ -171,23 +193,43 @@ esp_err_t esp_tls_set_global_ca_store(const unsigned char *cacert_pem_buf, const ESP_LOGE(TAG, "mbedtls_x509_crt_parse was partly successful. No. of failed certificates: %d", ret); } return ESP_OK; +#else + if (global_cacert != NULL) { + esp_tls_free_global_ca_store(global_cacert); + } + + 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; +#endif } -mbedtls_x509_crt *esp_tls_get_global_ca_store() +void *esp_tls_get_global_ca_store() { - return global_cacert; + return (void*)global_cacert; } void esp_tls_free_global_ca_store() { if (global_cacert) { +#if CONFIG_SSL_USING_MBEDTLS mbedtls_x509_crt_free(global_cacert); global_cacert = NULL; +#else + free(global_cacert); + global_cacert = NULL; + global_cacert_pem_bytes = 0; +#endif } } static void verify_certificate(esp_tls_t *tls) { +#if CONFIG_SSL_USING_MBEDTLS int flags; char buf[100]; if ((flags = mbedtls_ssl_get_verify_result(&tls->ssl)) != 0) { @@ -198,13 +240,22 @@ static void verify_certificate(esp_tls_t *tls) } else { ESP_LOGI(TAG, "Certificate verified."); } +#else + int flags; + if ((flags = wolfSSL_get_verify_result(tls->ssl)) != WOLFSSL_SUCCESS) { + ESP_LOGE(TAG, "Failed to verify peer certificate %d!", flags); + } else { + ESP_LOGI(TAG, "Certificate verified."); + } +#endif } -static void mbedtls_cleanup(esp_tls_t *tls) +static void esp_tls_cleanup(esp_tls_t *tls) { if (!tls) { return; } +#if CONFIG_SSL_USING_MBEDTLS if (tls->cacert_ptr != global_cacert) { mbedtls_x509_crt_free(tls->cacert_ptr); } @@ -217,12 +268,19 @@ static void mbedtls_cleanup(esp_tls_t *tls) mbedtls_ctr_drbg_free(&tls->ctr_drbg); mbedtls_ssl_free(&tls->ssl); mbedtls_net_free(&tls->server_fd); +#else + wolfSSL_shutdown(tls->ssl); + wolfSSL_free(tls->ssl); + close(tls->sockfd); + wolfSSL_CTX_free(tls->ctx); + wolfSSL_Cleanup(); +#endif } static int create_ssl_handle(esp_tls_t *tls, const char *hostname, size_t hostlen, const esp_tls_cfg_t *cfg) { int ret; - +#if CONFIG_SSL_USING_MBEDTLS mbedtls_net_init(&tls->server_fd); tls->server_fd.fd = tls->sockfd; mbedtls_ssl_init(&tls->ssl); @@ -326,8 +384,74 @@ static int create_ssl_handle(esp_tls_t *tls, const char *hostname, size_t hostle return 0; exit: - mbedtls_cleanup(tls); + esp_tls_cleanup(tls); return -1; +#else + ret = wolfSSL_Init(); + if (ret != WOLFSSL_SUCCESS) { + ESP_LOGE(TAG, "Init wolfSSL failed: %d", ret); + goto exit; + } + + tls->ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); + if (!tls->ctx) { + ESP_LOGE(TAG, "Set wolfSSL ctx failed"); + 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(tls->ssl, *alpn_list, strlen(*alpn_list), WOLFSSL_ALPN_FAILED_ON_MISMATCH) != WOLFSSL_SUCCESS) { + ESP_LOGE(TAG, "Use wolfSSL ALPN failed"); + goto exit; + } + } + } +#endif + + if (cfg->use_global_ca_store == true) { + wolfSSL_CTX_load_verify_buffer(tls->ctx, global_cacert, global_cacert_pem_bytes, WOLFSSL_FILETYPE_PEM); + wolfSSL_CTX_set_verify(tls->ctx, SSL_VERIFY_PEER, NULL); + } else if (cfg->cacert_pem_buf != NULL) { + wolfSSL_CTX_load_verify_buffer(tls->ctx, cfg->cacert_pem_buf, cfg->cacert_pem_bytes, WOLFSSL_FILETYPE_PEM); + wolfSSL_CTX_set_verify(tls->ctx, SSL_VERIFY_PEER, NULL); + } else { + wolfSSL_CTX_set_verify(tls->ctx, SSL_VERIFY_NONE, NULL); + } + + if (cfg->clientcert_pem_buf != NULL && cfg->clientkey_pem_buf != NULL) { + wolfSSL_CTX_use_certificate_buffer(tls->ctx, cfg->clientcert_pem_buf, cfg->clientcert_pem_bytes, WOLFSSL_FILETYPE_PEM); + wolfSSL_CTX_use_PrivateKey_buffer(tls->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->ssl = wolfSSL_new(tls->ctx); + if (!tls->ssl) { + ESP_LOGE(TAG, "Create wolfSSL failed"); + 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(tls->ssl, use_host); + free(use_host); +#endif + + wolfSSL_set_fd(tls->ssl, tls->sockfd); + + return 0; +exit: + esp_tls_cleanup(tls); + return -1; +#endif } /** @@ -336,7 +460,7 @@ exit: void esp_tls_conn_delete(esp_tls_t *tls) { if (tls != NULL) { - mbedtls_cleanup(tls); + esp_tls_cleanup(tls); if (tls->sockfd) { close(tls->sockfd); } @@ -351,6 +475,7 @@ static ssize_t tcp_write(esp_tls_t *tls, const char *data, size_t datalen) static ssize_t tls_write(esp_tls_t *tls, const char *data, size_t datalen) { +#if CONFIG_SSL_USING_MBEDTLS ssize_t ret = mbedtls_ssl_write(&tls->ssl, (unsigned char*) data, datalen); if (ret < 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { @@ -358,6 +483,15 @@ static ssize_t tls_write(esp_tls_t *tls, const char *data, size_t datalen) } } return ret; +#else + ssize_t ret = wolfSSL_write(tls->ssl, (unsigned char*) data, datalen); + if (ret < 0) { + if (ret != WOLFSSL_ERROR_WANT_READ && ret != WOLFSSL_ERROR_WANT_WRITE) { + ESP_LOGE(TAG, "write error :%d:", ret); + } + } + return ret; +#endif } static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_t *tls) @@ -427,6 +561,7 @@ static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, c /* falls through */ case ESP_TLS_HANDSHAKE: ESP_LOGD(TAG, "handshake in progress..."); +#if CONFIG_SSL_USING_MBEDTLS ret = mbedtls_ssl_handshake(&tls->ssl); if (ret == 0) { tls->conn_state = ESP_TLS_DONE; @@ -445,6 +580,26 @@ static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, c or MBEDTLS_ERR_SSL_WANT_WRITE during handshake */ return 0; } +#else + ret = wolfSSL_connect(tls->ssl); + if (ret == WOLFSSL_SUCCESS) { + tls->conn_state = ESP_TLS_DONE; + return 1; + } else { + if (ret != WOLFSSL_ERROR_WANT_READ && ret != WOLFSSL_ERROR_WANT_WRITE) { + ESP_LOGE(TAG, "wolfSSL_connect returned -0x%x", -ret); + if (cfg->cacert_pem_buf != NULL || cfg->use_global_ca_store == true) { + /* This is to check whether handshake failed due to invalid certificate*/ + 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; + } +#endif break; case ESP_TLS_FAIL: ESP_LOGE(TAG, "failed to open a new connection");; @@ -490,9 +645,13 @@ int esp_tls_conn_new_async(const char *hostname, int hostlen, int port, const es size_t esp_tls_get_bytes_avail(esp_tls_t *tls) { +#if CONFIG_SSL_USING_MBEDTLS 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); +#else + return 0; +#endif } diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h index 3782c0e9..246d7e81 100644 --- a/components/esp-tls/esp_tls.h +++ b/components/esp-tls/esp_tls.h @@ -18,6 +18,7 @@ #include #include +#if CONFIG_SSL_USING_MBEDTLS #include "mbedtls/platform.h" #include "mbedtls/net_sockets.h" #include "mbedtls/esp_debug.h" @@ -26,6 +27,9 @@ #include "mbedtls/ctr_drbg.h" #include "mbedtls/error.h" #include "mbedtls/certs.h" +#else +#include "wolfssl/ssl.h" +#endif #ifdef __cplusplus extern "C" { @@ -90,6 +94,7 @@ typedef struct esp_tls_cfg { * @brief ESP-TLS Connection Handle */ typedef struct esp_tls { +#if CONFIG_SSL_USING_MBEDTLS mbedtls_ssl_context ssl; /*!< TLS/SSL context */ mbedtls_entropy_context entropy; /*!< mbedTLS entropy context structure */ @@ -112,7 +117,10 @@ typedef struct esp_tls { mbedtls_pk_context clientkey; /*!< Container for the private key of the client certificate */ - +#else + WOLFSSL_CTX *ctx; + WOLFSSL *ssl; +#endif int sockfd; /*!< Underlying socket file descriptor. */ ssize_t (*esp_tls_read)(struct esp_tls *tls, char *data, size_t datalen); /*!< Callback function for reading data from TLS/SSL @@ -258,7 +266,7 @@ esp_err_t esp_tls_set_global_ca_store(const unsigned char *cacert_pem_buf, const * - 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 *esp_tls_get_global_ca_store(); /** * @brief Free the global CA store currently being used.