tcp_transport: Extend transport error storage for socket error

Everytime we report error and log errno, we also capture the actual
errno to an internal storage so that user application can retrieve
its value.
This commit is contained in:
David Cermak 2020-04-08 20:04:33 +02:00 committed by bot
parent 1a35b5ac9b
commit ce519ee783
13 changed files with 251 additions and 86 deletions

View File

@ -1,4 +1,4 @@
set(srcs esp_tls.c esp-tls-crypto/esp_tls_crypto.c)
set(srcs esp_tls.c esp-tls-crypto/esp_tls_crypto.c esp_tls_error_capture.c)
if(CONFIG_ESP_TLS_USING_MBEDTLS)
list(APPEND srcs
"esp_tls_mbedtls.c")

View File

@ -1,6 +1,6 @@
COMPONENT_SRCDIRS := . esp-tls-crypto
COMPONENT_OBJS := esp_tls.o esp-tls-crypto/esp_tls_crypto.o
COMPONENT_OBJS := esp_tls.o esp-tls-crypto/esp_tls_crypto.o esp_tls_error_capture.o
COMPONENT_ADD_INCLUDEDIRS := . esp-tls-crypto private_include

View File

@ -108,7 +108,7 @@ int esp_tls_conn_destroy(esp_tls_t *tls)
if (tls->sockfd >= 0) {
ret = close(tls->sockfd);
}
free(tls->error_handle);
esp_tls_internal_event_tracker_destroy(tls->error_handle);
free(tls);
return ret;
}
@ -121,7 +121,7 @@ esp_tls_t *esp_tls_init(void)
if (!tls) {
return NULL;
}
tls->error_handle = calloc(1, sizeof(esp_tls_last_error_t));
tls->error_handle = esp_tls_internal_event_tracker_create();
if (!tls->error_handle) {
free(tls);
return NULL;
@ -172,7 +172,7 @@ static esp_err_t esp_tcp_connect(const char *host, int hostlen, int port, int *s
int fd = socket(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol);
if (fd < 0) {
ESP_LOGE(TAG, "Failed to create socket (family %d socktype %d protocol %d)", addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_SYSTEM, errno);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_SYSTEM, errno);
ret = ESP_ERR_ESP_TLS_CANNOT_CREATE_SOCKET;
goto err_freeaddr;
}
@ -214,7 +214,7 @@ static esp_err_t esp_tcp_connect(const char *host, int hostlen, int port, int *s
if (ret < 0 && !(errno == EINPROGRESS && cfg && cfg->non_block)) {
ESP_LOGE(TAG, "Failed to connnect to host (errno %d)", errno);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_SYSTEM, errno);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_SYSTEM, errno);
ret = ESP_ERR_ESP_TLS_FAILED_CONNECT_TO_HOST;
goto err_freesocket;
}
@ -249,7 +249,7 @@ static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, c
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);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, esp_ret);
return -1;
}
if (!cfg) {
@ -284,8 +284,8 @@ static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, c
/* 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);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_SYSTEM, errno);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED);
tls->conn_state = ESP_TLS_FAIL;
return -1;
}
@ -295,7 +295,7 @@ static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, c
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);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, esp_ret);
tls->conn_state = ESP_TLS_FAIL;
return -1;
}
@ -367,7 +367,7 @@ int esp_tls_conn_new_sync(const char *hostname, int hostlen, int port, const esp
uint32_t expired = xTaskGetTickCount() - start;
if (expired >= timeout_ticks) {
ESP_LOGW(TAG, "Failed to open new connection in specified timeout");
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT);
return 0;
}
}

View File

@ -74,6 +74,22 @@ extern "C" {
#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 */
/**
* Definition of different types/sources of error codes reported
* from different components
*/
typedef enum {
ESP_TLS_ERR_TYPE_UNKNOWN = 0,
ESP_TLS_ERR_TYPE_SYSTEM, /*!< System error -- errno */
ESP_TLS_ERR_TYPE_MBEDTLS, /*!< Error code from mbedTLS library */
ESP_TLS_ERR_TYPE_MBEDTLS_CERT_FLAGS, /*!< Certificate flags defined in mbedTLS */
ESP_TLS_ERR_TYPE_ESP, /*!< ESP-IDF error type -- esp_err_t */
ESP_TLS_ERR_TYPE_WOLFSSL, /*!< Error code from wolfSSL library */
ESP_TLS_ERR_TYPE_WOLFSSL_CERT_FLAGS, /*!< Certificate flags defined in wolfSSL */
ESP_TLS_ERR_TYPE_MAX, /*!< Last err type -- invalid entry */
} esp_tls_error_type_t;
typedef struct esp_tls_last_error* esp_tls_error_handle_t;
/**
@ -574,6 +590,20 @@ void esp_tls_free_global_ca_store(void);
*/
esp_err_t esp_tls_get_and_clear_last_error(esp_tls_error_handle_t h, int *esp_tls_code, int *esp_tls_flags);
/**
* @brief Returns the last error captured in esp_tls of a specific type
* The error information is cleared internally upon return
*
* @param[in] h esp-tls error handle.
* @param[in] err_type specific error type
* @param[out] error_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
* @return
* - ESP_ERR_INVALID_STATE if invalid parameters
* - ESP_OK if a valid error returned and was cleared
*/
esp_err_t esp_tls_get_and_clear_error_type(esp_tls_error_handle_t h, esp_tls_error_type_t err_type, int *error_code);
#if CONFIG_ESP_TLS_USING_MBEDTLS
/**
* @brief Get the pointer to the global CA store currently being used.

View File

@ -0,0 +1,81 @@
// Copyright 2020 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 "esp_tls.h"
#include "esp_tls_error_capture_internal.h"
typedef struct esp_tls_error_storage {
struct esp_tls_last_error parent; /*!< standard esp-tls last error container */
int sock_errno; /*!< last socket error captured in esp-tls */
} esp_tls_error_storage_t;
void esp_tls_internal_event_tracker_capture(esp_tls_error_handle_t h, uint32_t type, int code)
{
if (h) {
esp_tls_error_storage_t * storage = __containerof(h, esp_tls_error_storage_t, parent);
if (type == ESP_TLS_ERR_TYPE_ESP) {
storage->parent.last_error = code;
} else if (type == ESP_TLS_ERR_TYPE_MBEDTLS ||
type == ESP_TLS_ERR_TYPE_WOLFSSL) {
storage->parent.esp_tls_error_code = code;
} else if (type == ESP_TLS_ERR_TYPE_MBEDTLS_CERT_FLAGS ||
type == ESP_TLS_ERR_TYPE_WOLFSSL_CERT_FLAGS) {
storage->parent.esp_tls_flags = code;
} else if (type == ESP_TLS_ERR_TYPE_SYSTEM) {
storage->sock_errno = code;
}
}
}
esp_tls_error_handle_t esp_tls_internal_event_tracker_create(void)
{
// Allocating internal error storage which extends the parent type
// `esp_tls_last_error` defined at interface level
struct esp_tls_error_storage* storage =
calloc(1, sizeof(struct esp_tls_error_storage));
return &storage->parent;
}
void esp_tls_internal_event_tracker_destroy(esp_tls_error_handle_t h)
{
esp_tls_error_storage_t * storage = __containerof(h, esp_tls_error_storage_t, parent);
free(storage);
}
esp_err_t esp_tls_get_and_clear_error_type(esp_tls_error_handle_t h, esp_tls_error_type_t type, int *code)
{
if (h && type < ESP_TLS_ERR_TYPE_MAX && code) {
esp_tls_error_storage_t * storage = __containerof(h, esp_tls_error_storage_t, parent);
if (type == ESP_TLS_ERR_TYPE_ESP) {
*code = storage->parent.last_error;
storage->parent.last_error = 0;
} else if (type == ESP_TLS_ERR_TYPE_MBEDTLS ||
type == ESP_TLS_ERR_TYPE_WOLFSSL) {
*code = storage->parent.esp_tls_error_code;
storage->parent.esp_tls_error_code = 0;
} else if (type == ESP_TLS_ERR_TYPE_MBEDTLS_CERT_FLAGS ||
type == ESP_TLS_ERR_TYPE_WOLFSSL_CERT_FLAGS) {
*code = storage->parent.esp_tls_flags;
storage->parent.esp_tls_flags = 0;
} else if (type == ESP_TLS_ERR_TYPE_SYSTEM) {
*code = storage->sock_errno;
storage->sock_errno = 0;
} else {
return ESP_ERR_INVALID_ARG;
}
return ESP_OK;
}
return ESP_ERR_INVALID_ARG;
}

View File

@ -100,7 +100,7 @@ esp_err_t esp_create_mbedtls_handle(const char *hostname, size_t hostlen, const
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_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
esp_ret = ESP_ERR_MBEDTLS_CTR_DRBG_SEED_FAILED;
goto exit;
}
@ -113,7 +113,7 @@ esp_err_t esp_create_mbedtls_handle(const char *hostname, size_t hostlen, const
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_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
esp_ret = ESP_ERR_MBEDTLS_SSL_SETUP_FAILED;
goto exit;
}
@ -140,8 +140,8 @@ int esp_mbedtls_handshake(esp_tls_t *tls, const esp_tls_cfg_t *cfg)
} else {
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);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_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);
@ -164,7 +164,7 @@ ssize_t esp_mbedtls_read(esp_tls_t *tls, char *data, size_t datalen)
return 0;
}
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_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
ESP_LOGE(TAG, "read error :%d:", ret);
}
}
@ -185,8 +185,8 @@ 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 != 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_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, ESP_ERR_MBEDTLS_SSL_WRITE_FAILED);
ESP_LOGE(TAG, "write error :%d:", ret);
return ret;
} else {
@ -217,7 +217,7 @@ void esp_mbedtls_verify_certificate(esp_tls_t *tls)
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);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_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);
@ -271,7 +271,7 @@ static esp_err_t set_ca_cert(esp_tls_t *tls, const unsigned char *cacert, size_t
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);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED;
}
mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
@ -295,7 +295,7 @@ static esp_err_t set_pki_context(esp_tls_t *tls, const esp_tls_pki_t *pki)
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);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED;
}
@ -317,14 +317,14 @@ static esp_err_t set_pki_context(esp_tls_t *tls, const esp_tls_pki_t *pki)
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);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_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);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
return ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED;
}
} else {
@ -359,7 +359,7 @@ esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls)
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);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
return ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED;
}
@ -421,7 +421,7 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t
/* 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);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
free(use_host);
return ESP_ERR_MBEDTLS_SSL_SET_HOSTNAME_FAILED;
}
@ -433,7 +433,7 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t
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);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
return ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED;
}
@ -445,7 +445,7 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t
#ifdef CONFIG_MBEDTLS_SSL_ALPN
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);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
return ESP_ERR_MBEDTLS_SSL_CONF_ALPN_PROTOCOLS_FAILED;
}
#else
@ -483,7 +483,7 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t
(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);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
return ESP_ERR_MBEDTLS_SSL_CONF_PSK_FAILED;
}
#else
@ -570,7 +570,7 @@ int esp_mbedtls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp
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);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, esp_ret);
tls->conn_state = ESP_TLS_FAIL;
return -1;
}
@ -703,7 +703,7 @@ static esp_err_t esp_set_atecc608a_pki_context(esp_tls_t *tls, esp_tls_cfg_t *cf
ret = mbedtls_x509_crt_parse(&tls->clientcert, (const unsigned char*)cfg->clientcert_buf, cfg->clientcert_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);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED;
}
} else {
@ -714,14 +714,14 @@ static esp_err_t esp_set_atecc608a_pki_context(esp_tls_t *tls, esp_tls_cfg_t *cf
ret = atca_mbedtls_pk_init(&tls->clientkey, 0);
if (ret != 0) {
ESP_LOGE(TAG, "Failed to parse key from device");
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
return ESP_ERR_ESP_TLS_SE_FAILED;
}
ret = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->clientcert, &tls->clientkey);
if (ret != 0) {
ESP_LOGE(TAG, "Failed\n ! mbedtls_ssl_conf_own_cert returned -0x%x", ret);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_MBEDTLS, -ret);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
return ESP_ERR_ESP_TLS_SE_FAILED;
}
return ESP_OK;

View File

@ -114,7 +114,7 @@ esp_err_t esp_create_wolfssl_handle(const char *hostname, size_t hostlen, const
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);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -ret);
goto exit;
}
@ -153,7 +153,7 @@ static esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls
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);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -ret);
return ESP_ERR_WOLFSSL_CTX_SETUP_FAILED;
}
@ -226,7 +226,7 @@ static esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls
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);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -ret);
return ESP_ERR_WOLFSSL_SSL_SETUP_FAILED;
}
@ -243,7 +243,7 @@ static esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls
/* Hostname set here should match CN in server certificate */
if ((ret = wolfSSL_set_tlsext_host_name( (WOLFSSL *)tls->priv_ssl, use_host))!= WOLFSSL_SUCCESS) {
ESP_LOGE(TAG, "wolfSSL_set_tlsext_host_name returned -0x%x", -ret);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL, -ret);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -ret);
free(use_host);
return ESP_ERR_WOLFSSL_SSL_SET_HOSTNAME_FAILED;
}
@ -256,7 +256,7 @@ static esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls
for (; *alpn_list != NULL; alpn_list ++) {
ESP_LOGD(TAG, "alpn protocol is %s", *alpn_list);
if ((ret = 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_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -ret);
ESP_LOGE(TAG, "wolfSSL UseALPN failed, returned %d", ret);
return ESP_ERR_WOLFSSL_SSL_CONF_ALPN_PROTOCOLS_FAILED;
}
@ -329,8 +329,8 @@ int esp_wolfssl_handshake(esp_tls_t *tls, const esp_tls_cfg_t *cfg)
int err = wolfSSL_get_error( (WOLFSSL *)tls->priv_ssl, ret);
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);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_WOLFSSL_SSL_HANDSHAKE_FAILED);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -ret);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, ESP_ERR_WOLFSSL_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_wolfssl_verify_certificate(tls);
@ -355,7 +355,7 @@ ssize_t esp_wolfssl_read(esp_tls_t *tls, char *data, size_t datalen)
}
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_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -ret);
ESP_LOGE(TAG, "read error :%d:", ret);
}
}
@ -368,8 +368,8 @@ ssize_t esp_wolfssl_write(esp_tls_t *tls, const char *data, size_t datalen)
if (ret < 0) {
ret = wolfSSL_get_error( (WOLFSSL *)tls->priv_ssl, ret);
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_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_ESP, ESP_ERR_WOLFSSL_SSL_WRITE_FAILED);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -ret);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, ESP_ERR_WOLFSSL_SSL_WRITE_FAILED);
ESP_LOGE(TAG, "write error :%d:", ret);
}
@ -382,7 +382,7 @@ void esp_wolfssl_verify_certificate(esp_tls_t *tls)
int flags;
if ((flags = wolfSSL_get_verify_result( (WOLFSSL *)tls->priv_ssl)) != X509_V_OK) {
ESP_LOGE(TAG, "Failed to verify peer certificate , returned %d!", flags);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ERR_TYPE_WOLFSSL_CERT_FLAGS, flags);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL_CERT_FLAGS, flags);
} else {
ESP_LOGI(TAG, "Certificate verified.");
}
@ -434,7 +434,7 @@ int esp_wolfssl_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp
esp_err_t esp_ret = esp_create_wolfssl_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);
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, esp_ret);
tls->conn_state = ESP_TLS_FAIL;
return -1;
}
@ -443,7 +443,7 @@ int esp_wolfssl_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp
int ret;
while ((ret = wolfSSL_accept((WOLFSSL *)tls->priv_ssl)) != WOLFSSL_SUCCESS) {
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_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -ret);
ESP_LOGE(TAG, "wolfSSL_handshake_server returned %d", ret);
tls->conn_state = ESP_TLS_FAIL;
return ret;

View File

@ -24,43 +24,36 @@ extern "C" {
#endif
/**
* Definition of different types/sources of error codes reported
* from different components
*/
typedef enum {
ERR_TYPE_UNKNOWN = 0,
ERR_TYPE_SYSTEM,
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 to enable mapping tracking errors internally
* or using an external/global implementation
*/
#define ESP_INT_EVENT_TRACKER_CAPTURE(h, type, code) esp_tls_internal_event_tracker_capture(h, type, code)
/**
* Error tracker logging macro, this implementation saves latest errors of
* ERR_TYPE_ESP, ERR_TYPE_ESP_TLS and ERR_TYPE_ESP_TLS_CERT_FLAGS types
* @brief Internal tracker capture error
*
* This implementation saves latest errors of available types
*
* @param[in] h esp-tls error handle
* @param[in] err_type Specific error type
* @param[int] code Error code to capture
*
*/
#define ESP_INT_EVENT_TRACKER_CAPTURE(h, type, code) esp_int_event_tracker_capture(h, type, code)
static inline void esp_int_event_tracker_capture(esp_tls_error_handle_t h, uint32_t type, int code)
{
if (h) {
if (type == ERR_TYPE_ESP) {
h->last_error = code;
} else if (type == ERR_TYPE_MBEDTLS) {
h->esp_tls_error_code = code;
} else if (type == ERR_TYPE_MBEDTLS_CERT_FLAGS) {
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;
}
}
}
void esp_tls_internal_event_tracker_capture(esp_tls_error_handle_t h, uint32_t type, int code);
/**
* @brief Create internal tracker storage
*
* @return Error tracker handle if success or NULL if allocation error
*/
esp_tls_error_handle_t esp_tls_internal_event_tracker_create(void);
/**
* @brief Destroy internal tracker storage
*
* @param[in] h esp-tls error handle
*/
void esp_tls_internal_event_tracker_destroy(esp_tls_error_handle_t h);
#ifdef __cplusplus
}

View File

@ -313,7 +313,22 @@ esp_err_t esp_transport_set_parent_transport_func(esp_transport_handle_t t, payl
*/
esp_tls_error_handle_t esp_transport_get_error_handle(esp_transport_handle_t t);
/**
* @brief Get and clear last captured socket errno
*
* Socket errno is internally stored whenever any of public facing API
* for reading, writing, polling or connection fails returning negative return code.
* The error code corresponds to the `SO_ERROR` value retrieved from the underlying
* transport socket using `getsockopt()` API. After reading the captured errno,
* the internal value is cleared to 0.
*
* @param[in] t The transport handle
*
* @return
* - >=0 Last captured socket errno
* - -1 Invalid transport handle or invalid transport's internal error storage
*/
int esp_transport_get_errno(esp_transport_handle_t t);
#ifdef __cplusplus
}

View File

@ -36,8 +36,9 @@ struct esp_transport_item_t {
trans_func _destroy; /*!< Destroy and free transport */
connect_async_func _connect_async; /*!< non-blocking connect function of this transport */
payload_transfer_func _parent_transfer; /*!< Function returning underlying transport layer */
get_socket_func _get_socket;
esp_tls_error_handle_t error_handle; /*!< Pointer to esp-tls error handle */
get_socket_func _get_socket; /*!< Function returning the transport's socket */
struct esp_transport_error_s* error_handle; /*!< Error handle (based on esp-tls error handle)
* extended with transport's specific errors */
STAILQ_ENTRY(esp_transport_item_t) next;
};
@ -52,5 +53,13 @@ struct esp_transport_item_t {
*/
int esp_transport_get_socket(esp_transport_handle_t t);
/**
* @brief Captures the current errno
*
* @param[in] t The transport handle
* @param[in] sock_errno Socket errno to store in internal transport structures
*
*/
void esp_transport_capture_errno(esp_transport_handle_t t, int sock_errno);
#endif //_ESP_TRANSPORT_INTERNAL_H_

View File

@ -26,7 +26,16 @@
static const char *TAG = "TRANSPORT";
/**
* Transport layer error structure including
* * esp-tls last error storage
* * sock-errno
*/
struct esp_transport_error_s {
struct esp_tls_last_error esp_tls_err_h_base; /*!< esp-tls last error container */
// additional fields
int sock_errno; /*!< last socket error captured for this transport */
};
/**
* This list will hold all transport available
@ -38,7 +47,7 @@ STAILQ_HEAD(esp_transport_list_t, esp_transport_item_t);
*/
typedef struct esp_transport_internal {
struct esp_transport_list_t list; /*!< List of transports */
esp_tls_error_handle_t error_handle; /*!< Pointer to the error tracker if enabled */
struct esp_transport_error_s* error_handle; /*!< Pointer to the transport error container */
} esp_transport_internal_t;
static esp_transport_handle_t esp_transport_get_default_parent(esp_transport_handle_t t)
@ -54,7 +63,7 @@ esp_transport_list_handle_t esp_transport_list_init(void)
esp_transport_list_handle_t transport = calloc(1, sizeof(esp_transport_internal_t));
ESP_TRANSPORT_MEM_CHECK(TAG, transport, return NULL);
STAILQ_INIT(&transport->list);
transport->error_handle = calloc(1, sizeof(esp_tls_last_error_t));
transport->error_handle = calloc(1, sizeof(struct esp_transport_error_s));
return transport;
}
@ -274,15 +283,36 @@ esp_err_t esp_transport_set_parent_transport_func(esp_transport_handle_t t, payl
esp_tls_error_handle_t esp_transport_get_error_handle(esp_transport_handle_t t)
{
if (t) {
return t->error_handle;
return &t->error_handle->esp_tls_err_h_base;
}
return NULL;
}
int esp_transport_get_errno(esp_transport_handle_t t)
{
if (t && t->error_handle) {
int actual_errno = t->error_handle->sock_errno;
t->error_handle->sock_errno = 0;
return actual_errno;
}
return -1;
}
void esp_transport_set_errors(esp_transport_handle_t t, const esp_tls_error_handle_t error_handle)
{
if (t) {
memcpy(t->error_handle, error_handle, sizeof(esp_tls_last_error_t));
if (t && t->error_handle) {
memcpy(&t->error_handle->esp_tls_err_h_base, error_handle, sizeof(esp_tls_last_error_t));
int sock_error;
if (esp_tls_get_and_clear_error_type(error_handle, ESP_TLS_ERR_TYPE_SYSTEM, &sock_error) == ESP_OK) {
t->error_handle->sock_errno = sock_error;
}
}
}
void esp_transport_capture_errno(esp_transport_handle_t t, int sock_errno)
{
if (t && t->error_handle) {
t->error_handle->sock_errno = sock_errno;
}
}

View File

@ -105,6 +105,7 @@ static int ssl_poll_read(esp_transport_handle_t t, int timeout_ms)
int sock_errno = 0;
uint32_t optlen = sizeof(sock_errno);
getsockopt(ssl->tls->sockfd, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen);
esp_transport_capture_errno(t, sock_errno);
ESP_LOGE(TAG, "ssl_poll_read select error %d, errno = %s, fd = %d", sock_errno, strerror(sock_errno), ssl->tls->sockfd);
ret = -1;
}
@ -127,6 +128,7 @@ static int ssl_poll_write(esp_transport_handle_t t, int timeout_ms)
int sock_errno = 0;
uint32_t optlen = sizeof(sock_errno);
getsockopt(ssl->tls->sockfd, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen);
esp_transport_capture_errno(t, sock_errno);
ESP_LOGE(TAG, "ssl_poll_write select error %d, errno = %s, fd = %d", sock_errno, strerror(sock_errno), ssl->tls->sockfd);
ret = -1;
}

View File

@ -107,10 +107,12 @@ static int tcp_connect(esp_transport_handle_t t, const char *host, int port, int
int res = select(tcp->sock+1, NULL, &fdset, NULL, &tv);
if (res < 0) {
ESP_LOGE(TAG, "[sock=%d] select() error: %s", tcp->sock, strerror(errno));
esp_transport_capture_errno(t, errno);
goto error;
}
else if (res == 0) {
ESP_LOGE(TAG, "[sock=%d] select() timeout", tcp->sock);
esp_transport_capture_errno(t, EINPROGRESS); // errno=EINPROGRESS indicates connection timeout
goto error;
} else {
int sockerr;
@ -121,6 +123,7 @@ static int tcp_connect(esp_transport_handle_t t, const char *host, int port, int
goto error;
}
else if (sockerr) {
esp_transport_capture_errno(t, sockerr);
ESP_LOGE(TAG, "[sock=%d] delayed connect error: %s", tcp->sock, strerror(sockerr));
goto error;
}
@ -187,6 +190,7 @@ static int tcp_poll_read(esp_transport_handle_t t, int timeout_ms)
int sock_errno = 0;
uint32_t optlen = sizeof(sock_errno);
getsockopt(tcp->sock, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen);
esp_transport_capture_errno(t, sock_errno);
ESP_LOGE(TAG, "tcp_poll_read select error %d, errno = %s, fd = %d", sock_errno, strerror(sock_errno), tcp->sock);
ret = -1;
}
@ -210,6 +214,7 @@ static int tcp_poll_write(esp_transport_handle_t t, int timeout_ms)
int sock_errno = 0;
uint32_t optlen = sizeof(sock_errno);
getsockopt(tcp->sock, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen);
esp_transport_capture_errno(t, sock_errno);
ESP_LOGE(TAG, "tcp_poll_write select error %d, errno = %s, fd = %d", sock_errno, strerror(sock_errno), tcp->sock);
ret = -1;
}