From f74447103fc11f6388f966551d0c5263c6fc97d6 Mon Sep 17 00:00:00 2001 From: yuanjianmin Date: Thu, 20 Apr 2023 17:45:25 +0800 Subject: [PATCH 1/3] esp-tls: Add config and api to set and get ciphersuites list --- components/esp-tls/esp_tls.c | 5 +++++ components/esp-tls/esp_tls.h | 11 +++++++++++ components/esp-tls/esp_tls_mbedtls.c | 10 ++++++++++ components/esp-tls/private_include/esp_tls_mbedtls.h | 5 +++++ 4 files changed, 31 insertions(+) diff --git a/components/esp-tls/esp_tls.c b/components/esp-tls/esp_tls.c index 799c30acf6..1461728ab1 100644 --- a/components/esp-tls/esp_tls.c +++ b/components/esp-tls/esp_tls.c @@ -74,6 +74,7 @@ static const char *TAG = "esp-tls"; #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 */ +#define _esp_tls_get_ciphersuites_list esp_mbedtls_get_ciphersuites_list #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 @@ -617,6 +618,10 @@ mbedtls_x509_crt *esp_tls_get_global_ca_store(void) return _esp_tls_get_global_ca_store(); } +const int *esp_tls_get_ciphersuites_list(void) +{ + return _esp_tls_get_ciphersuites_list(); +} #endif /* CONFIG_ESP_TLS_USING_MBEDTLS */ #ifdef CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h index 555caed37d..5543b0d0f4 100644 --- a/components/esp-tls/esp_tls.h +++ b/components/esp-tls/esp_tls.h @@ -193,6 +193,8 @@ typedef struct esp_tls_cfg { #endif /* CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS */ esp_tls_addr_family_t addr_family; /*!< The address family to use when connecting to a host. */ + const int *ciphersuites_list; /*!< Pointer to a zero-terminated array of IANA identifiers of TLS ciphersuites. + Please check the list validity by esp_tls_get_ciphersuites_list() API */ } esp_tls_cfg_t; #ifdef CONFIG_ESP_TLS_SERVER @@ -649,6 +651,15 @@ esp_err_t esp_tls_get_error_handle(esp_tls_t *tls, esp_tls_error_handle_t *error */ mbedtls_x509_crt *esp_tls_get_global_ca_store(void); +/** + * @brief Get supported TLS ciphersuites list. + * + * See https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4 for the list of ciphersuites + * + * @return Pointer to a zero-terminated array of IANA identifiers of TLS ciphersuites. + * + */ +const int *esp_tls_get_ciphersuites_list(void); #endif /* CONFIG_ESP_TLS_USING_MBEDTLS */ #ifdef CONFIG_ESP_TLS_SERVER /** diff --git a/components/esp-tls/esp_tls_mbedtls.c b/components/esp-tls/esp_tls_mbedtls.c index 79921f0c36..d264eaea0e 100644 --- a/components/esp-tls/esp_tls_mbedtls.c +++ b/components/esp-tls/esp_tls_mbedtls.c @@ -788,6 +788,11 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t ESP_LOGE(TAG, "You have to provide both clientcert_buf and clientkey_buf for mutual authentication"); return ESP_ERR_INVALID_STATE; } + + if (cfg->ciphersuites_list != NULL && cfg->ciphersuites_list[0] != 0) { + ESP_LOGD(TAG, "Set the ciphersuites list"); + mbedtls_ssl_conf_ciphersuites(&tls->conf, cfg->ciphersuites_list); + } return ESP_OK; } @@ -895,6 +900,11 @@ void esp_mbedtls_free_global_ca_store(void) } } +const int *esp_mbedtls_get_ciphersuites_list(void) +{ + return mbedtls_ssl_list_ciphersuites(); +} + #ifdef CONFIG_ESP_TLS_USE_SECURE_ELEMENT static esp_err_t esp_init_atecc608a(uint8_t i2c_addr) { diff --git a/components/esp-tls/private_include/esp_tls_mbedtls.h b/components/esp-tls/private_include/esp_tls_mbedtls.h index 3eb46a0807..5526bba98c 100644 --- a/components/esp-tls/private_include/esp_tls_mbedtls.h +++ b/components/esp-tls/private_include/esp_tls_mbedtls.h @@ -136,3 +136,8 @@ 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); + +/** + * Internal Callback for esp_tls_get_ciphersuites_list + */ +const int *esp_mbedtls_get_ciphersuites_list(void); From 3f58b33c7fd0e909a6f6cb3c1b0bdf5d0b2b386b Mon Sep 17 00:00:00 2001 From: yuanjianmin Date: Thu, 20 Apr 2023 20:42:01 +0800 Subject: [PATCH 2/3] example: Add example to test ciphersuites set function --- .../main/https_request_example_main.c | 22 +++++++++++++++++- .../https_request/pytest_https_request.py | 23 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) 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 f386ed4e2a..c0d22b4fe9 100644 --- a/examples/protocols/https_request/main/https_request_example_main.c +++ b/examples/protocols/https_request/main/https_request_example_main.c @@ -84,7 +84,8 @@ extern const uint8_t server_root_cert_pem_end[] asm("_binary_server_root_cert_ extern const uint8_t local_server_cert_pem_start[] asm("_binary_local_server_cert_pem_start"); extern const uint8_t local_server_cert_pem_end[] asm("_binary_local_server_cert_pem_end"); - +static const int server_supported_ciphersuites[] = {MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 0}; +static const int server_unsupported_ciphersuites[] = {MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, 0}; #ifdef CONFIG_EXAMPLE_CLIENT_SESSION_TICKETS static esp_tls_client_session_t *tls_client_session = NULL; static bool save_client_session = false; @@ -185,6 +186,24 @@ static void https_get_request_using_cacert_buf(void) https_get_request(cfg, WEB_URL, HOWSMYSSL_REQUEST); } +static void https_get_request_using_specified_ciphersuites(void) +{ + ESP_LOGI(TAG, "https_request using server supported ciphersuites"); + esp_tls_cfg_t cfg = { + .cacert_buf = (const unsigned char *) server_root_cert_pem_start, + .cacert_bytes = server_root_cert_pem_end - server_root_cert_pem_start, + .ciphersuites_list = server_supported_ciphersuites, + }; + + https_get_request(cfg, WEB_URL, HOWSMYSSL_REQUEST); + + ESP_LOGI(TAG, "https_request using server unsupported ciphersuites"); + + cfg.ciphersuites_list = server_unsupported_ciphersuites; + + https_get_request(cfg, WEB_URL, HOWSMYSSL_REQUEST); +} + static void https_get_request_using_global_ca_store(void) { esp_err_t esp_ret = ESP_FAIL; @@ -259,6 +278,7 @@ static void https_request_task(void *pvparameters) ESP_LOGI(TAG, "Minimum free heap size: %" PRIu32 " bytes", esp_get_minimum_free_heap_size()); https_get_request_using_cacert_buf(); https_get_request_using_global_ca_store(); + https_get_request_using_specified_ciphersuites(); ESP_LOGI(TAG, "Finish https_request example"); vTaskDelete(NULL); } diff --git a/examples/protocols/https_request/pytest_https_request.py b/examples/protocols/https_request/pytest_https_request.py index bf8922b930..0afcda609e 100644 --- a/examples/protocols/https_request/pytest_https_request.py +++ b/examples/protocols/https_request/pytest_https_request.py @@ -211,3 +211,26 @@ def test_examples_protocol_https_request(dut: Dut) -> None: logging.info("Failed the test for \"https_request using global ca_store\"") raise logging.info("Passed the test for \"https_request using global ca_store\"") + + # Check for connection using specified server supported ciphersuites + logging.info("Testing for \"https_request using server supported ciphersuites\"") + try: + dut.expect('https_request using server supported ciphersuites', timeout=20) + dut.expect(['Connection established...', + 'Reading HTTP response...', + 'HTTP/1.1 200 OK', + 'connection closed'], expect_all=True) + except Exception: + logging.info("Failed the test for \"https_request using server supported ciphersuites\"") + raise + logging.info("Passed the test for \"https_request using server supported ciphersuites\"") + + # Check for connection using specified server unsupported ciphersuites + logging.info("Testing for \"https_request using server unsupported ciphersuites\"") + try: + dut.expect('https_request using server unsupported ciphersuites', timeout=20) + dut.expect('Connection failed...', timeout=30) + except Exception: + logging.info("Failed the test for \"https_request using server unsupported ciphersuites\"") + raise + logging.info("Passed the test for \"https_request using server unsupported ciphersuites\"") From e4e2bd24c97ad6ce9e78eb359d90ea64a0f422aa Mon Sep 17 00:00:00 2001 From: yuanjianmin Date: Fri, 21 Apr 2023 10:57:19 +0800 Subject: [PATCH 3/3] doc: Add support to set and get ciphersuites list --- docs/en/api-reference/protocols/esp_tls.rst | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/en/api-reference/protocols/esp_tls.rst b/docs/en/api-reference/protocols/esp_tls.rst index a05f3da1b4..03f54da940 100644 --- a/docs/en/api-reference/protocols/esp_tls.rst +++ b/docs/en/api-reference/protocols/esp_tls.rst @@ -192,6 +192,25 @@ SSL/TLS libraries and with all respective configurations set to default. * An example of mutual authentication with the DS peripheral can be found at :example:`ssl mutual auth` which internally uses (ESP-TLS) for the TLS connection. +TLS Ciphersuites +------------------------------------ +ESP-TLS provides an ability to set a ciphersuites list in the client mode. TLS ciphersuites list helps to inform the server about the supported ciphersuites for the specific TLS connection (irrespective of the TLS stack configuration). If the server supports any ciphersuite from this list then the TLS connection shall succeed, otherwise it would fail. + +You can set ``ciphersuites_list`` in the :cpp:type:`esp_tls_cfg_t` structure during client connection as follows: + +.. code-block:: c + + /* ciphersuites_list must end with 0 and must be available in the memory scope active during the entire TLS connection */ + static const int ciphersuites_list[] = {MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 0}; + esp_tls_cfg_t cfg = { + .ciphersuites_list = ciphersuites_list, + }; + +ESP-TLS will not check the validity of ``ciphersuites_list`` that was set, you should call :cpp:func:`esp_tls_get_ciphersuites_list` to get ciphersuites list supported in the TLS stack and cross-check it against the supplied list. + +.. note:: + This feature is supported only in the mbedTLS stack. + API Reference -------------