Skip to content

Commit

Permalink
Merge branch 'feature/add_mbedtls_ciphersuites_set_get_api' into 'mas…
Browse files Browse the repository at this point in the history
…ter'

esp-tls: Add config and api to set and get ciphersuites list

Closes IDF-7183

See merge request espressif/esp-idf!23320
  • Loading branch information
mahavirj committed Apr 28, 2023
2 parents 542c705 + e4e2bd2 commit b5055b9
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 1 deletion.
5 changes: 5 additions & 0 deletions components/esp-tls/esp_tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions components/esp-tls/esp_tls.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
/**
Expand Down
10 changes: 10 additions & 0 deletions components/esp-tls/esp_tls_mbedtls.c
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,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;
}

Expand Down Expand Up @@ -911,6 +916,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)
{
Expand Down
5 changes: 5 additions & 0 deletions components/esp-tls/private_include/esp_tls_mbedtls.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
19 changes: 19 additions & 0 deletions docs/en/api-reference/protocols/esp_tls.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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<protocols/mqtt/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
-------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down
23 changes: 23 additions & 0 deletions examples/protocols/https_request/pytest_https_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -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\"")

0 comments on commit b5055b9

Please sign in to comment.