diff --git a/components/esp-tls/esp_tls.c b/components/esp-tls/esp_tls.c index 7ecccbed..094292dd 100644 --- a/components/esp-tls/esp_tls.c +++ b/components/esp-tls/esp_tls.c @@ -20,20 +20,12 @@ #include #include +#include #include "esp_tls.h" #include -#if LWIP_IPV6 -#define ESP_TLS_IPV6 -#endif - static const char *TAG = "esp-tls"; -#if CONFIG_SSL_USING_MBEDTLS static mbedtls_x509_crt *global_cacert = NULL; -#elif CONFIG_SSL_USING_WOLFSSL -static unsigned char *global_cacert = NULL; -static unsigned int global_cacert_pem_bytes = 0; -#endif #ifdef ESP_PLATFORM #include @@ -72,7 +64,6 @@ 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) { @@ -80,27 +71,8 @@ static ssize_t tls_read(esp_tls_t *tls, char *data, size_t datalen) } if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { ESP_LOGE(TAG, "read error :%d:", ret); - } else { - ret = (ret == MBEDTLS_ERR_SSL_WANT_READ) ? ESP_TLS_ERROR_WANT_READ : ESP_TLS_ERROR_WANT_WRITE; } } -#elif CONFIG_SSL_USING_WOLFSSL - - ssize_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); - } else { - ret = (ret == WOLFSSL_ERROR_WANT_READ) ? ESP_TLS_ERROR_WANT_READ : ESP_TLS_ERROR_WANT_WRITE; - } - } -#endif return ret; } @@ -123,20 +95,17 @@ static int esp_tcp_connect(const char *host, int hostlen, int port, int *sockfd, ESP_LOGE(TAG, "Failed to create socket (family %d socktype %d protocol %d)", res->ai_family, res->ai_socktype, res->ai_protocol); goto err_freeaddr; } - *sockfd = fd; void *addr_ptr; if (res->ai_family == AF_INET) { struct sockaddr_in *p = (struct sockaddr_in *)res->ai_addr; p->sin_port = htons(port); addr_ptr = p; -#ifdef ESP_TLS_IPV6 } else if (res->ai_family == AF_INET6) { struct sockaddr_in6 *p = (struct sockaddr_in6 *)res->ai_addr; p->sin6_port = htons(port); p->sin6_family = AF_INET6; addr_ptr = p; -#endif } else { ESP_LOGE(TAG, "Unsupported protocol family %d", res->ai_family); goto err_freesocket; @@ -155,12 +124,13 @@ static int esp_tcp_connect(const char *host, int hostlen, int port, int *sockfd, } ret = connect(fd, addr_ptr, res->ai_addrlen); - if (ret < 0 && !(errno == EINPROGRESS && cfg->non_block)) { + if (ret < 0 && !(errno == EINPROGRESS && cfg && cfg->non_block)) { - ESP_LOGE(TAG, "Failed to connnect to host (errno %d)", errno); + ESP_LOGE(TAG, "Failed to connect to host (errno %d)", errno); goto err_freesocket; } + *sockfd = fd; freeaddrinfo(res); return 0; @@ -171,24 +141,33 @@ err_freeaddr: return ret; } +esp_err_t esp_tls_init_global_ca_store() +{ + 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 CONFIG_SSL_USING_MBEDTLS - if (global_cacert != NULL) { - mbedtls_x509_crt_free(global_cacert); - } - 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; + ret = esp_tls_init_global_ca_store(); + if (ret != ESP_OK) { + return ret; + } } - mbedtls_x509_crt_init(global_cacert); - int ret = mbedtls_x509_crt_parse(global_cacert, cacert_pem_buf, cacert_pem_bytes); + 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\n\n", -ret); mbedtls_x509_crt_free(global_cacert); @@ -198,43 +177,23 @@ 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; -#elif CONFIG_SSL_USING_WOLFSSL - 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 } -void *esp_tls_get_global_ca_store() +mbedtls_x509_crt *esp_tls_get_global_ca_store() { - return (void*)global_cacert; + return 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; -#elif CONFIG_SSL_USING_WOLFSSL - 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) { @@ -245,22 +204,13 @@ static void verify_certificate(esp_tls_t *tls) } else { ESP_LOGI(TAG, "Certificate verified."); } -#elif CONFIG_SSL_USING_WOLFSSL - 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 esp_tls_cleanup(esp_tls_t *tls) +static void mbedtls_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); } @@ -272,21 +222,12 @@ static void esp_tls_cleanup(esp_tls_t *tls) mbedtls_ssl_config_free(&tls->conf); mbedtls_ctr_drbg_free(&tls->ctr_drbg); mbedtls_ssl_free(&tls->ssl); - mbedtls_net_free(&tls->server_fd); -#elif CONFIG_SSL_USING_WOLFSSL - 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); mbedtls_ctr_drbg_init(&tls->ctr_drbg); @@ -299,18 +240,26 @@ static int create_ssl_handle(esp_tls_t *tls, const char *hostname, size_t hostle goto exit; } - /* Hostname set here should match CN in server certificate */ - char *use_host = strndup(hostname, hostlen); - if (!use_host) { - goto exit; - } + 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 ((ret = mbedtls_ssl_set_hostname(&tls->ssl, use_host)) != 0) { - ESP_LOGE(TAG, "mbedtls_ssl_set_hostname returned -0x%x", -ret); + if (use_host == NULL) { + goto exit; + } + + /* 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); + free(use_host); + goto exit; + } free(use_host); - goto exit; } - free(use_host); if ((ret = mbedtls_ssl_config_defaults(&tls->conf, MBEDTLS_SSL_IS_CLIENT, @@ -389,74 +338,8 @@ static int create_ssl_handle(esp_tls_t *tls, const char *hostname, size_t hostle return 0; exit: - esp_tls_cleanup(tls); + mbedtls_cleanup(tls); return -1; -#elif CONFIG_SSL_USING_WOLFSSL - 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 } /** @@ -465,8 +348,10 @@ exit: void esp_tls_conn_delete(esp_tls_t *tls) { if (tls != NULL) { - esp_tls_cleanup(tls); - if (tls->sockfd) { + mbedtls_cleanup(tls); + if (tls->is_tls) { + mbedtls_net_free(&tls->server_fd); + } else if (tls->sockfd >= 0) { close(tls->sockfd); } free(tls); @@ -480,28 +365,13 @@ 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) { ESP_LOGE(TAG, "write error :%d:", ret); - } else { - ret = (ret == MBEDTLS_ERR_SSL_WANT_READ) ? ESP_TLS_ERROR_WANT_READ : ESP_TLS_ERROR_WANT_WRITE; } } return ret; -#elif CONFIG_SSL_USING_WOLFSSL - ssize_t ret = wolfSSL_write(tls->ssl, (unsigned char*) data, datalen); - if (ret < 0) { - ret = wolfSSL_get_error(tls->ssl, ret); - if (ret != WOLFSSL_ERROR_WANT_READ && ret != WOLFSSL_ERROR_WANT_WRITE) { - ESP_LOGE(TAG, "write error :%d:", ret); - } else { - ret = (ret == WOLFSSL_ERROR_WANT_READ) ? ESP_TLS_ERROR_WANT_READ : ESP_TLS_ERROR_WANT_WRITE; - } - } - 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) @@ -514,16 +384,18 @@ static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, c and in case of blocking connect these cases will get executed one after the other */ switch (tls->conn_state) { case ESP_TLS_INIT: - ; - int sockfd; - int ret = esp_tcp_connect(hostname, hostlen, port, &sockfd, cfg); + tls->sockfd = -1; + if (cfg != NULL) { + mbedtls_net_init(&tls->server_fd); + tls->is_tls = true; + } + int ret = esp_tcp_connect(hostname, hostlen, port, &tls->sockfd, cfg); if (ret < 0) { return -1; } - tls->sockfd = sockfd; if (!cfg) { - tls->esp_tls_read = tcp_read; - tls->esp_tls_write = tcp_write; + tls->read = tcp_read; + tls->write = tcp_write; ESP_LOGD(TAG, "non-tls connection established"); return 1; } @@ -565,13 +437,12 @@ static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, c tls->conn_state = ESP_TLS_FAIL; return -1; } - tls->esp_tls_read = tls_read; - tls->esp_tls_write = tls_write; + 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..."); -#if CONFIG_SSL_USING_MBEDTLS ret = mbedtls_ssl_handshake(&tls->ssl); if (ret == 0) { tls->conn_state = ESP_TLS_DONE; @@ -590,27 +461,6 @@ 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; } -#elif CONFIG_SSL_USING_WOLFSSL - ret = wolfSSL_connect(tls->ssl); - if (ret == WOLFSSL_SUCCESS) { - tls->conn_state = ESP_TLS_DONE; - return 1; - } else { - int err = wolfSSL_get_error(tls->ssl, ret); - if (err != WOLFSSL_ERROR_WANT_READ && err != 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");; @@ -654,15 +504,55 @@ int esp_tls_conn_new_async(const char *hostname, int hostlen, int port, const es return esp_tls_low_level_conn(hostname, hostlen, port, cfg, tls); } +static int get_port(const char *url, struct http_parser_url *u) +{ + if (u->field_data[UF_PORT].len) { + return strtol(&url[u->field_data[UF_PORT].off], NULL, 10); + } else { + if (strncasecmp(&url[u->field_data[UF_SCHEMA].off], "http", u->field_data[UF_SCHEMA].len) == 0) { + return 80; + } else if (strncasecmp(&url[u->field_data[UF_SCHEMA].off], "https", u->field_data[UF_SCHEMA].len) == 0) { + return 443; + } + } + return 0; +} + +/** + * @brief Create a new TLS/SSL connection with a given "HTTP" url + */ +esp_tls_t *esp_tls_conn_http_new(const char *url, const esp_tls_cfg_t *cfg) +{ + /* Parse URI */ + struct http_parser_url u; + http_parser_url_init(&u); + http_parser_parse_url(url, strlen(url), 0, &u); + + /* Connect to host */ + return esp_tls_conn_new(&url[u.field_data[UF_HOST].off], u.field_data[UF_HOST].len, + get_port(url, &u), cfg); +} + size_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 ESP_FAIL; } -#if CONFIG_SSL_USING_MBEDTLS return mbedtls_ssl_get_bytes_avail(&tls->ssl); -#elif CONFIG_SSL_USING_WOLFSSL - return wolfSSL_pending(tls->ssl); -#endif } + +/** + * @brief Create a new non-blocking TLS/SSL connection with a given "HTTP" url + */ +int esp_tls_conn_http_new_async(const char *url, const esp_tls_cfg_t *cfg, esp_tls_t *tls) +{ + /* Parse URI */ + struct http_parser_url u; + http_parser_url_init(&u); + http_parser_parse_url(url, strlen(url), 0, &u); + + /* 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); +} \ No newline at end of file diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h index afbd18d4..41faa5b0 100644 --- a/components/esp-tls/esp_tls.h +++ b/components/esp-tls/esp_tls.h @@ -18,7 +18,6 @@ #include #include -#if CONFIG_SSL_USING_MBEDTLS #include "mbedtls/platform.h" #include "mbedtls/net_sockets.h" #include "mbedtls/esp_debug.h" @@ -27,19 +26,11 @@ #include "mbedtls/ctr_drbg.h" #include "mbedtls/error.h" #include "mbedtls/certs.h" -#else -#include "wolfssl/ssl.h" -#endif #ifdef __cplusplus extern "C" { #endif -typedef enum { - ESP_TLS_ERROR_WANT_READ = -2, - ESP_TLS_ERROR_WANT_WRITE = -3, -} esp_tls_error_t; - /** * @brief ESP-TLS Connection State */ @@ -65,17 +56,20 @@ typedef struct esp_tls_cfg { - where the first '2' is the length of the protocol and - the subsequent 'h2' is the protocol name */ - const unsigned char *cacert_pem_buf; /*!< Certificate Authority's certificate in a buffer */ + const unsigned char *cacert_pem_buf; /*!< Certificate Authority's certificate in a buffer. + This buffer should be NULL terminated */ unsigned int cacert_pem_bytes; /*!< Size of Certificate Authority certificate pointed to by cacert_pem_buf */ - const unsigned char *clientcert_pem_buf;/*!< Client certificate in a buffer */ + const unsigned char *clientcert_pem_buf;/*!< Client certificate in a buffer + This buffer should be NULL terminated */ unsigned int clientcert_pem_bytes; /*!< Size of client certificate pointed to by clientcert_pem_buf */ - const unsigned char *clientkey_pem_buf; /*!< Client key in a buffer */ + const unsigned char *clientkey_pem_buf; /*!< Client key in a buffer + This buffer should be NULL terminated */ unsigned int clientkey_pem_bytes; /*!< Size of client key pointed to by clientkey_pem_buf */ @@ -93,13 +87,17 @@ typedef struct esp_tls_cfg { bool use_global_ca_store; /*!< Use a global ca_store for all the connections in which this bool is set. */ + + const char *common_name; /*!< If non-NULL, server certificate CN must match this name. + If NULL, server certificate CN must match hostname. */ + + bool skip_common_name; /*!< Skip any validation of server certificate CN field */ } esp_tls_cfg_t; /** * @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 */ @@ -122,16 +120,13 @@ 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 + ssize_t (*read)(struct esp_tls *tls, char *data, size_t datalen); /*!< Callback function for reading data from TLS/SSL connection. */ - ssize_t (*esp_tls_write)(struct esp_tls *tls, const char *data, size_t datalen); /*!< Callback function for writing data to TLS/SSL + ssize_t (*write)(struct esp_tls *tls, const char *data, size_t datalen); /*!< Callback function for writing data to TLS/SSL connection. */ esp_tls_conn_state_t conn_state; /*!< ESP-TLS Connection state */ @@ -139,6 +134,8 @@ typedef struct esp_tls { fd_set rset; /*!< read file descriptors */ fd_set wset; /*!< write file descriptors */ + + bool is_tls; /*!< indicates connection type (TLS or NON-TLS) */ } esp_tls_t; /** @@ -156,6 +153,20 @@ typedef struct esp_tls { * @return pointer to esp_tls_t, or NULL if connection couldn't be opened. */ esp_tls_t *esp_tls_conn_new(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg); + +/** + * @brief Create a new blocking TLS/SSL connection with a given "HTTP" url + * + * The behaviour is same as esp_tls_conn_new() API. However this API accepts host's url. + * + * @param[in] url url of host. + * @param[in] cfg TLS configuration as esp_tls_cfg_t. If you wish to open + * non-TLS connection, keep this NULL. For TLS connection, + * a pass pointer to 'esp_tls_cfg_t'. At a minimum, this + * structure should be zero-initialized. + * @return pointer to esp_tls_t, or NULL if connection couldn't be opened. + */ +esp_tls_t *esp_tls_conn_http_new(const char *url, const esp_tls_cfg_t *cfg); /** * @brief Create a new non-blocking TLS/SSL connection @@ -177,6 +188,22 @@ esp_tls_t *esp_tls_conn_new(const char *hostname, int hostlen, int port, const e */ int esp_tls_conn_new_async(const char *hostname, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_t *tls); +/** + * @brief Create a new non-blocking TLS/SSL connection with a given "HTTP" url + * + * The behaviour is same as esp_tls_conn_new() API. However this API accepts host's url. + * + * @param[in] url url of host. + * @param[in] cfg TLS configuration as esp_tls_cfg_t. + * @param[in] tls pointer to esp-tls as esp-tls handle. + * + * @return + * - -1 If connection establishment fails. + * - 0 If connection establishment is in progress. + * - 1 If connection establishment is successful. + */ +int esp_tls_conn_http_new_async(const char *url, const esp_tls_cfg_t *cfg, esp_tls_t *tls); + /** * @brief Write from buffer 'data' into specified tls connection. * @@ -194,7 +221,7 @@ int esp_tls_conn_new_async(const char *hostname, int hostlen, int port, const es */ static inline ssize_t esp_tls_conn_write(esp_tls_t *tls, const void *data, size_t datalen) { - return tls->esp_tls_write(tls, (char *)data, datalen); + return tls->write(tls, (char *)data, datalen); } /** @@ -214,7 +241,7 @@ static inline ssize_t esp_tls_conn_write(esp_tls_t *tls, const void *data, size_ */ static inline ssize_t esp_tls_conn_read(esp_tls_t *tls, void *data, size_t datalen) { - return tls->esp_tls_read(tls, (char *)data, datalen); + return tls->read(tls, (char *)data, datalen); } /** @@ -243,10 +270,25 @@ void esp_tls_conn_delete(esp_tls_t *tls); size_t esp_tls_get_bytes_avail(esp_tls_t *tls); /** - * @brief Create a global CA store with the buffer provided in cfg. + * @brief Create a global CA store, initially empty. * - * This function should be called if the application wants to use the same CA store for - * multiple connections. The application must call this function before calling esp_tls_conn_new(). + * This function should be called if the application wants to use the same CA store for multiple connections. + * This function initialises the global CA store which can be then set by calling esp_tls_set_global_ca_store(). + * To be effective, this function must be called before any call to esp_tls_set_global_ca_store(). + * + * @return + * - ESP_OK if creating global CA store was successful. + * - ESP_ERR_NO_MEM if an error occured when allocating the mbedTLS resources. + */ +esp_err_t esp_tls_init_global_ca_store(); + +/** + * @brief Set the global CA store with the buffer provided in pem format. + * + * This function should be called if the application wants to set the global CA store for + * multiple connections i.e. to add the certificates in the provided buffer to the certificate chain. + * This function implicitly calls esp_tls_init_global_ca_store() if it has not already been called. + * The application must call this function before calling esp_tls_conn_new(). * * @param[in] cacert_pem_buf Buffer which has certificates in pem format. This buffer * is used for creating a global CA store, which can be used @@ -254,7 +296,7 @@ size_t esp_tls_get_bytes_avail(esp_tls_t *tls); * @param[in] cacert_pem_bytes Length of the buffer. * * @return - * - ESP_OK if creating global CA store was successful. + * - ESP_OK if adding certificates was successful. * - Other if an error occured or an action must be taken by the calling process. */ esp_err_t esp_tls_set_global_ca_store(const unsigned char *cacert_pem_buf, const unsigned int cacert_pem_bytes); @@ -271,7 +313,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. */ -void *esp_tls_get_global_ca_store(); +mbedtls_x509_crt *esp_tls_get_global_ca_store(); /** * @brief Free the global CA store currently being used.