chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
ASIO Port
|
||||
=========
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
ASIO is a cross-platform C++ library, see https://think-async.com/Asio/. It provides a consistent asynchronous model using a modern C++ approach.
|
||||
|
||||
The ESP-IDF component ``ASIO`` has been moved from ESP-IDF since version v5.0 to a separate repository:
|
||||
|
||||
* `ASIO component on GitHub <https://github.com/espressif/esp-protocols/tree/master/components/asio>`__
|
||||
|
||||
To add ASIO component in your project, please run ``idf.py add-dependency espressif/asio``.
|
||||
|
||||
Hosted Documentation
|
||||
--------------------
|
||||
|
||||
The documentation can be found on the link below:
|
||||
|
||||
* `ASIO documentation (English) <https://docs.espressif.com/projects/esp-protocols/asio/docs/latest/index.html>`__
|
||||
@@ -0,0 +1,123 @@
|
||||
ESP x509 Certificate Bundle
|
||||
===========================
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
The ESP x509 Certificate Bundle API provides an easy way to include a bundle of custom x509 root certificates for TLS server verification.
|
||||
|
||||
The bundle comes with the complete list of root certificates from Mozilla's NSS root certificate store. Using the gen_crt_bundle.py python utility, the certificates' subject name and public key are stored in a file and embedded in the {IDF_TARGET_NAME} binary.
|
||||
|
||||
When generating the bundle you may choose between:
|
||||
|
||||
* The full root certificate bundle from Mozilla, containing more than 130 certificates. The current bundle was updated Thu May 14 03:12:02 2026 GMT.
|
||||
* A pre-selected filter list of the name of the most commonly used root certificates, reducing the amount of certificates to around 35 while still having around 94% absolute usage coverage and 99% market share coverage according to SSL certificate authorities statistics.
|
||||
|
||||
In addition, it is possible to specify a path to a certificate file or a directory containing certificates which then will be added to the generated bundle.
|
||||
|
||||
.. note::
|
||||
|
||||
Trusting all root certificates means the list will have to be updated if any of the certificates are retracted. This includes removing them from ``cacrt_all.pem``.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
Most configuration is done through menuconfig. CMake generates the bundle according to the configuration and embed it.
|
||||
|
||||
* :ref:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE`: automatically build and attach the bundle.
|
||||
* :ref:`CONFIG_MBEDTLS_DEFAULT_CERTIFICATE_BUNDLE`: decide which certificates to include from the complete root certificate list.
|
||||
* :ref:`CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH`: specify the path of any additional certificates to embed in the bundle.
|
||||
|
||||
To enable the bundle when using ESP-TLS simply pass the function pointer to the bundle attach function:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
esp_tls_cfg_t cfg = {
|
||||
.crt_bundle_attach = esp_crt_bundle_attach,
|
||||
};
|
||||
|
||||
This is done to avoid embedding the certificate bundle unless activated by the user.
|
||||
|
||||
If using mbedTLS directly then the bundle may be activated by directly calling the attach function during the setup process:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
mbedtls_ssl_config conf;
|
||||
mbedtls_ssl_config_init(&conf);
|
||||
|
||||
esp_crt_bundle_attach(&conf);
|
||||
|
||||
|
||||
.. _updating_bundle:
|
||||
|
||||
Generating the List of Root Certificates
|
||||
----------------------------------------
|
||||
|
||||
The list of root certificates comes from Mozilla's NSS root certificate store, which can be found `here <https://wiki.mozilla.org/CA/Included_Certificates>`_
|
||||
|
||||
The list can be downloaded and created by running the script ``mk-ca-bundle.pl`` that is distributed as a part of `curl <https://github.com/curl/curl>`_.
|
||||
|
||||
Another alternative would be to download the finished list directly from the curl website: `CA certificates extracted from Mozilla <https://curl.se/docs/caextract.html>`_
|
||||
|
||||
The common certificates bundle were made by selecting the authorities with a market share of more than 1% from w3tech's `SSL Survey <https://w3techs.com/technologies/overview/ssl_certificate>`_.
|
||||
|
||||
These authorities were then used to pick the names of the certificates for the filter list, ``cmn_crt_authorities.csv``, from Mozilla's `Included CA Certificate List <https://ccadb.my.salesforce-sites.com/mozilla/IncludedRootCertificateReportCSVFormat>`_.
|
||||
|
||||
|
||||
Updating the Certificate Bundle
|
||||
-------------------------------
|
||||
|
||||
The bundle is embedded into the app and can be updated along with the app by an OTA update. If you want to include a more up-to-date bundle than the bundle currently included in ESP-IDF, then the certificate list can be downloaded from Mozilla as described in :ref:`updating_bundle`.
|
||||
|
||||
|
||||
Periodic Sync
|
||||
-------------
|
||||
|
||||
The bundle is kept updated by periodic sync with the Mozilla's NSS root certificate store. The deprecated certs from the upstream bundle are added to deprecated list (for compatibility reasons) in ESP-IDF minor or patch release. If required, the deprecated certs can be added to the default bundle by enabling :ref:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEPRECATED_LIST`. The deprecated certs shall be removed (reset) on the next major ESP-IDF release.
|
||||
|
||||
Cross-Signed Certificate Support
|
||||
---------------------------------
|
||||
|
||||
Overview
|
||||
^^^^^^^^
|
||||
|
||||
When the configuration option :ref:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_CROSS_SIGNED_VERIFY` is enabled, the ESP x509 Certificate Bundle API adds support for verifying certificate chains that include cross-signed root certificates.
|
||||
|
||||
This feature allows the verification process to dynamically select candidate Certificate Authorities (CAs) from the bundle, even when the certificate chain contains cross-signed roots, improving interoperability with a wider range of server certificates.
|
||||
|
||||
With this functionality enabled, certificate verification is performed in a manner equivalent to the default mbedTLS behavior, ensuring compatibility and robust validation for cross-signed chains.
|
||||
|
||||
.. note::
|
||||
|
||||
Enabling cross-signed certificate support increases peak run-time heap usage during the TLS handshake by approximately 1 KB. This is a transient allocation (a candidate CA certificate built during certificate verification) that is freed once the handshake completes, and the exact amount scales with the maximum supported RSA key size. It also reduces the flash footprint, as the bundle size is reduced.
|
||||
|
||||
Key Points:
|
||||
|
||||
- The bundle can act as a dynamic CA store, providing candidate root certificates during the handshake.
|
||||
- The verification callback uses the issuer information from the certificate chain to locate and provide matching root certificates from the bundle.
|
||||
- This is especially useful for environments where cross-signing is common, such as during root CA transitions.
|
||||
|
||||
Usage
|
||||
^^^^^
|
||||
|
||||
No additional application changes are required beyond enabling :ref:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_CROSS_SIGNED_VERIFY` in your project configuration. The bundle will automatically provide candidate CAs during the TLS handshake.
|
||||
|
||||
.. note::
|
||||
|
||||
If :ref:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_CROSS_SIGNED_VERIFY` is enabled, it internally uses ``MBEDTLS_X509_TRUSTED_CERT_CALLBACK``. In this case, users should **not** provide their own trusted certificate callback, as the certificate bundle will manage this automatically.
|
||||
|
||||
Application Examples
|
||||
--------------------
|
||||
|
||||
- :example:`protocols/https_x509_bundle` demonstrates how to use ESP-TLS to establish a secure socket connection using the certificate bundle with two custom certificates added for verification.
|
||||
|
||||
- :example:`protocols/https_request` demonstrates an HTTPS example that uses ESP-TLS and the default bundle.
|
||||
|
||||
- :example:`protocols/https_mbedtls` demonstrates an HTTPS example that uses Mbed TLS and the default bundle.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
.. include-build-file:: inc/esp_crt_bundle.inc
|
||||
@@ -0,0 +1,248 @@
|
||||
ESP HTTP Client
|
||||
===============
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
``esp_http_client`` component provides a set of APIs for making HTTP/S requests from ESP-IDF applications. The steps to use these APIs are as follows:
|
||||
|
||||
* :cpp:func:`esp_http_client_init`: Creates an :cpp:type:`esp_http_client_handle_t` instance, i.e., an HTTP client handle based on the given :cpp:type:`esp_http_client_config_t` configuration. This function must be the first to be called; default values are assumed for the configuration values that are not explicitly defined by the user.
|
||||
* :cpp:func:`esp_http_client_perform`: Performs all operations of the ``esp_http_client`` - opening the connection, exchanging data, and closing the connection (as required), while blocking the current task before its completion. All related events are invoked through the event handler (as specified in :cpp:type:`esp_http_client_config_t`).
|
||||
* :cpp:func:`esp_http_client_cleanup`: Closes the connection (if any) and frees up all the memory allocated to the HTTP client instance. This must be the last function to be called after the completion of operations.
|
||||
|
||||
|
||||
Application Examples
|
||||
--------------------
|
||||
|
||||
- :example:`protocols/esp_http_client` demonstrates how to use the ESP HTTP Client to make HTTP/S requests.
|
||||
- :example:`protocols/esp_http_client_mutual_auth` demonstrates how to configure mutual TLS authentication with the ESP HTTP Client.
|
||||
|
||||
|
||||
Basic HTTP Request
|
||||
------------------
|
||||
|
||||
Check out the example functions ``http_rest_with_url`` and ``http_rest_with_hostname_path`` in the application example for implementation details.
|
||||
|
||||
|
||||
Persistent Connections
|
||||
----------------------
|
||||
|
||||
Persistent connection means that the HTTP client can reuse the same connection for several exchanges. If the server does not request to close the connection with the ``Connection: close`` header, the connection is not dropped but is instead kept open and used for further requests.
|
||||
|
||||
To allow ESP HTTP client to take full advantage of persistent connections, one should make as many requests as possible using the same handle instance. Check out the example functions ``http_rest_with_url`` and ``http_rest_with_hostname_path`` in the application example. Here, once the connection is created, multiple requests (``GET``, ``POST``, ``PUT``, etc.) are made before the connection is closed.
|
||||
|
||||
Use Secure Element (ATECC608) for TLS
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
A secure element (ATECC608) can be used for the underlying TLS connection in the HTTP client connection via the PSA Crypto opaque driver interface. Please refer to the **ATECC608A (Secure Element) with ESP-TLS** section in the :doc:`ESP-TLS documentation </api-reference/protocols/esp_tls>` for details on setting up the PSA key. Then configure the HTTP client to use the secure element via the ``client_key`` field in :cpp:type:`esp_http_client_config_t`:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
esp_key_config_t key_config = {
|
||||
.source = ESP_KEY_SOURCE_PSA,
|
||||
.psa.key_id = psa_key_id, /* obtained via psa_import_key() */
|
||||
};
|
||||
|
||||
esp_http_client_config_t cfg = {
|
||||
/* other configuration options */
|
||||
.client_key = &key_config,
|
||||
};
|
||||
|
||||
.. only:: SOC_ECDSA_SUPPORTED
|
||||
|
||||
Use ECDSA Digital Signature Peripheral (ECDSA_DS) for TLS
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The ECDSA Digital Signature Peripheral (ECDSA_DS) can be used for the underlying TLS connection in the HTTP client connection. Please refer to the **ECDSA Digital Signature Peripheral (ECDSA_DS) with ESP-TLS** section in the :doc:`ESP-TLS documentation </api-reference/protocols/esp_tls>` for more details. The HTTP client can be configured to use the ECDSA_DS peripheral as follows:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
esp_http_client_config_t cfg = {
|
||||
/* other configurations options */
|
||||
.use_ecdsa_peripheral = true,
|
||||
.ecdsa_key_efuse_blk = 4, // Low eFuse block for ECDSA key
|
||||
.ecdsa_key_efuse_blk_high = 5, // High eFuse block for ECDSA key (SECP384R1 only)
|
||||
.ecdsa_curve = ESP_TLS_ECDSA_CURVE_SECP384R1, // set this to ESP_TLS_ECDSA_CURVE_SECP256R1 for SECP256R1 curve
|
||||
};
|
||||
|
||||
|
||||
HTTPS Request
|
||||
-------------
|
||||
|
||||
ESP HTTP client supports SSL connections using **mbedTLS**, with the ``url`` configuration starting with ``https`` scheme or ``transport_type`` set to ``HTTP_TRANSPORT_OVER_SSL``. HTTPS support can be configured via :ref:`CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS` (enabled by default).
|
||||
|
||||
.. note::
|
||||
|
||||
While making HTTPS requests, if server verification is needed, an additional root certificate (in PEM format) needs to be provided to the ``cert_pem`` member in the ``esp_http_client_config_t`` configuration. Users can also use the ``ESP x509 Certificate Bundle`` for server verification using the ``crt_bundle_attach`` member of the ``esp_http_client_config_t`` configuration.
|
||||
|
||||
Check out the example functions ``https_with_url`` and ``https_with_hostname_path`` in the application example for implementation details of the above note.
|
||||
|
||||
|
||||
HTTP Stream
|
||||
-----------
|
||||
|
||||
Some applications need to open the connection and control the exchange of data actively (data streaming). In such cases, the application flow is different from regular requests. Example flow is given below:
|
||||
|
||||
* :cpp:func:`esp_http_client_init`: Create a HTTP client handle.
|
||||
* ``esp_http_client_set_*`` or ``esp_http_client_delete_*``: Modify the HTTP connection parameters (optional).
|
||||
* :cpp:func:`esp_http_client_open`: Open the HTTP connection with ``write_len`` parameter (content length that needs to be written to server), set ``write_len=0`` for read-only connection and set ``write_len=-1`` for chunked encoded data transfer.
|
||||
* :cpp:func:`esp_http_client_write`: Write data to server with a maximum length equal to ``write_len`` of :cpp:func:`esp_http_client_open` function; no need to call this function for ``write_len=0``.
|
||||
* :cpp:func:`esp_http_client_chunk_write_begin`: Begin a chunk by sending the chunk header (size line) when using chunked transfer encoding (``write_len=-1``).
|
||||
* :cpp:func:`esp_http_client_chunk_write_end`: End a chunk by sending the chunk trailer when using chunked transfer encoding.
|
||||
* :cpp:func:`esp_http_client_fetch_headers`: Read the HTTP Server response headers, after sending the request headers and server data (if any). Returns the ``content-length`` from the server and can be succeeded by :cpp:func:`esp_http_client_get_status_code` for getting the HTTP status of the connection.
|
||||
* :cpp:func:`esp_http_client_read`: Read the HTTP stream.
|
||||
* :cpp:func:`esp_http_client_close`: Close the connection.
|
||||
* :cpp:func:`esp_http_client_cleanup`: Release allocated resources.
|
||||
|
||||
Check out the example function ``http_perform_as_stream_reader`` in the application example for implementation details.
|
||||
|
||||
|
||||
HTTP Authentication
|
||||
-------------------
|
||||
|
||||
ESP HTTP client supports both **Basic** and **Digest** Authentication.
|
||||
* Users can provide the username and password in the ``url`` or the ``username`` and ``password`` members of the ``esp_http_client_config_t`` configuration. For ``auth_type = HTTP_AUTH_TYPE_BASIC``, the HTTP client takes only one perform operation to pass the authentication process.
|
||||
* If ``auth_type = HTTP_AUTH_TYPE_NONE``, but the ``username`` and ``password`` fields are present in the configuration, the HTTP client takes two perform operations. The client will receive the ``401 Unauthorized`` header in its first attempt to connect to the server. Based on this information, it decides which authentication method to choose and performs it in the second operation.
|
||||
* Check out the example functions ``http_auth_basic``, ``http_auth_basic_redirect`` (for Basic authentication) and ``http_auth_digest`` (for Digest authentication) in the application example for implementation details.
|
||||
* Currently, Digest authentication supports only MD5 and SHA-256 algorithms.
|
||||
|
||||
|
||||
Examples of Authentication Configuration
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
* Authentication with URI
|
||||
|
||||
.. highlight:: c
|
||||
|
||||
::
|
||||
|
||||
esp_http_client_config_t config = {
|
||||
.url = "http://user:passwd@httpbin.org/basic-auth/user/passwd",
|
||||
.auth_type = HTTP_AUTH_TYPE_BASIC,
|
||||
};
|
||||
|
||||
|
||||
* Authentication with username and password entry
|
||||
|
||||
.. highlight:: c
|
||||
|
||||
::
|
||||
|
||||
esp_http_client_config_t config = {
|
||||
.url = "http://httpbin.org/basic-auth/user/passwd",
|
||||
.username = "user",
|
||||
.password = "passwd",
|
||||
.auth_type = HTTP_AUTH_TYPE_BASIC,
|
||||
};
|
||||
|
||||
Response Header Access
|
||||
----------------------
|
||||
|
||||
ESP HTTP Client provides the ability to save and retrieve HTTP response headers from the server. This feature is useful when applications need to access metadata such as content type, cache control directives, custom server headers, or other response information.
|
||||
|
||||
Configuration
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
To enable response header saving, the following Kconfig options must be configured:
|
||||
|
||||
* :ref:`CONFIG_ESP_HTTP_CLIENT_SAVE_RESPONSE_HEADERS`: Enable saving of response headers (disabled by default to conserve memory).
|
||||
* :ref:`CONFIG_ESP_HTTP_CLIENT_MAX_SAVED_RESPONSE_HEADERS`: Maximum number of response headers to save (default: 10).
|
||||
* :ref:`CONFIG_ESP_HTTP_CLIENT_MAX_RESPONSE_HEADER_SIZE`: Maximum size in bytes for both header key and value (default: 128 bytes each).
|
||||
|
||||
Usage
|
||||
^^^^^
|
||||
|
||||
Once enabled, response headers can be retrieved using the :cpp:func:`esp_http_client_get_response_header` function after performing an HTTP request. The function returns the header value for a given key.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#if CONFIG_ESP_HTTP_CLIENT_SAVE_RESPONSE_HEADERS
|
||||
esp_http_client_handle_t client = esp_http_client_init(&config);
|
||||
esp_err_t err = esp_http_client_perform(client);
|
||||
|
||||
if (err == ESP_OK) {
|
||||
char *content_type = NULL;
|
||||
err = esp_http_client_get_response_header(client, "Content-Type", &content_type);
|
||||
if (err == ESP_OK && content_type != NULL) {
|
||||
ESP_LOGI(TAG, "Content-Type: %s", content_type);
|
||||
} else if (err == ESP_ERR_NOT_FOUND) {
|
||||
ESP_LOGW(TAG, "Content-Type header not found");
|
||||
}
|
||||
|
||||
char *date = NULL;
|
||||
err = esp_http_client_get_response_header(client, "Date", &date);
|
||||
if (err == ESP_OK && date != NULL) {
|
||||
ESP_LOGI(TAG, "Date: %s", date);
|
||||
}
|
||||
}
|
||||
|
||||
esp_http_client_cleanup(client);
|
||||
#endif
|
||||
|
||||
Important Limitations
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When using response header access, be aware of the following limitations:
|
||||
|
||||
* **Header Count Limit**: Only the first ``CONFIG_ESP_HTTP_CLIENT_MAX_SAVED_RESPONSE_HEADERS`` headers are saved. Additional headers beyond this limit are discarded with a warning log.
|
||||
* **Size Constraints**: Headers where either the key or value exceeds ``CONFIG_ESP_HTTP_CLIENT_MAX_RESPONSE_HEADER_SIZE`` bytes are discarded with a warning log showing the actual sizes.
|
||||
* **Multi-Value Headers**: For headers that appear multiple times in the response (e.g., ``Set-Cookie``), only the last value is retained.
|
||||
* **Case Sensitivity**: Header lookups are case-insensitive, but the original case is preserved in storage.
|
||||
* **Memory Overhead**: Enabling this feature increases memory consumption. Calculate approximate memory usage as: ``(CONFIG_ESP_HTTP_CLIENT_MAX_SAVED_RESPONSE_HEADERS * CONFIG_ESP_HTTP_CLIENT_MAX_RESPONSE_HEADER_SIZE * 2)`` bytes per client instance.
|
||||
* **Header Lifecycle**: Response headers are cleared when starting a new request with the same client handle via :cpp:func:`esp_http_client_perform` or :cpp:func:`esp_http_client_prepare`.
|
||||
|
||||
.. note::
|
||||
|
||||
The returned header value pointer is managed internally by the HTTP client and must not be freed by the application. The pointer remains valid until the client handle is cleaned up or a new request is initiated.
|
||||
|
||||
Event Handling
|
||||
--------------
|
||||
|
||||
ESP HTTP Client supports event handling by triggering an event handler corresponding to the event which takes place. :cpp:enum:`esp_http_client_event_id_t` contains all the events which could occur while performing an HTTP request using the ESP HTTP Client.
|
||||
|
||||
To enable event handling, you just need to set a callback function using the :cpp:member:`esp_http_client_config_t::event_handler` member.
|
||||
|
||||
Also you can set a callback function after the client is initialized using the :cpp:func:`esp_http_client_set_event_handler` function.
|
||||
|
||||
ESP HTTP Client Diagnostic Information
|
||||
--------------------------------------
|
||||
|
||||
Diagnostic information could be helpful to gain insights into a problem. In the case of ESP HTTP Client, the diagnostic information can be collected by registering an event handler with :doc:`the Event Loop library <../system/esp_event>`. This feature has been added by keeping in mind the `ESP Insights <https://github.com/espressif/esp-insights>`_ framework which collects the diagnostic information. However, this feature can also be used without any dependency on the ESP Insights framework for the diagnostic purpose. Event handler can be registered to the event loop using the :cpp:func:`esp_event_handler_register` function.
|
||||
|
||||
Expected data types for different HTTP Client events in the event loop are as follows:
|
||||
|
||||
- HTTP_EVENT_ERROR : ``esp_http_client_handle_t``
|
||||
- HTTP_EVENT_ON_CONNECTED : ``esp_http_client_handle_t``
|
||||
- HTTP_EVENT_HEADERS_SENT : ``esp_http_client_handle_t``
|
||||
- HTTP_EVENT_ON_HEADER : ``esp_http_client_handle_t``
|
||||
- HTTP_EVENT_ON_HEADERS_COMPLETE: ``esp_http_client_handle_t``
|
||||
- HTTP_EVENT_ON_STATUS_CODE : ``esp_http_client_handle_t``
|
||||
- HTTP_EVENT_ON_DATA : ``esp_http_client_on_data_t``
|
||||
- HTTP_EVENT_ON_FINISH : ``esp_http_client_handle_t``
|
||||
- HTTP_EVENT_DISCONNECTED : ``esp_http_client_handle_t``
|
||||
- HTTP_EVENT_REDIRECT : ``esp_http_client_redirect_event_data_t``
|
||||
|
||||
The :cpp:type:`esp_http_client_handle_t` received along with the event data will be valid until :cpp:enumerator:`HTTP_EVENT_DISCONNECTED <esp_http_client_event_id_t::HTTP_EVENT_DISCONNECTED>` is not received. This handle has been sent primarily to differentiate between different client connections and must not be used for any other purpose, as it may change based on client connection state.
|
||||
|
||||
TLS Protocol Version
|
||||
--------------------
|
||||
|
||||
TLS protocol version to be used for the underlying TLS connection can be set in :cpp:type:`esp_http_client_config_t`. Please refer to the **TLS Protocol Version** section in the :doc:`/api-reference/protocols/esp_tls` for more details.
|
||||
|
||||
The TLS protocol version for the HTTP client can be configured as follows:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include "esp_http_client.h"
|
||||
esp_http_client_config_t config = {
|
||||
.tls_version = ESP_HTTP_CLIENT_TLS_VER_TLS_1_2,
|
||||
};
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
.. include-build-file:: inc/esp_http_client.inc
|
||||
@@ -0,0 +1,219 @@
|
||||
HTTP Server
|
||||
===========
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
The HTTP Server component provides an ability for running a lightweight web server on {IDF_TARGET_NAME}. Following are detailed steps to use the API exposed by HTTP Server:
|
||||
|
||||
* :cpp:func:`httpd_start`: Creates an instance of HTTP server, allocate memory/resources for it depending upon the specified configuration and outputs a handle to the server instance. The server has both, a listening socket (TCP) for HTTP traffic, and a control socket (UDP) for control signals, which are selected in a round robin fashion in the server task loop. The task priority and stack size are configurable during server instance creation by passing ``httpd_config_t`` structure to ``httpd_start()``. TCP traffic is parsed as HTTP requests and, depending on the requested URI, user registered handlers are invoked which are supposed to send back HTTP response packets.
|
||||
* :cpp:func:`httpd_stop`: This stops the server with the provided handle and frees up any associated memory/resources. This is a blocking function that first signals a halt to the server task and then waits for the task to terminate. While stopping, the task closes all open connections, removes registered URI handlers and resets all session context data to empty.
|
||||
* :cpp:func:`httpd_register_uri_handler`: A URI handler is registered by passing object of type ``httpd_uri_t`` structure which has members including ``uri`` name, ``method`` type (eg. ``HTTP_GET/HTTP_POST/HTTP_PUT`` etc.), function pointer of type ``esp_err_t *handler (httpd_req_t *req)`` and ``user_ctx`` pointer to user context data.
|
||||
|
||||
.. note::
|
||||
|
||||
APIs in the HTTP server are not thread-safe. If thread safety is required, it is the responsibility of the application layer to ensure proper synchronization between multiple tasks.
|
||||
|
||||
Application Examples
|
||||
--------------------
|
||||
|
||||
- :example:`protocols/http_server/simple` demonstrates how to handle arbitrary content lengths, read request headers and URL query parameters, and set response headers.
|
||||
|
||||
- :example:`protocols/http_server/advanced_tests` demonstrates how to use the HTTP server for advanced testing.
|
||||
|
||||
Interface Binding
|
||||
-----------------
|
||||
|
||||
By default, the server listens on all available interfaces (``INADDR_ANY``). This is the behavior when ``httpd_config_t.if_name`` is ``NULL``.
|
||||
|
||||
To bind the HTTP server to a specific network interface, set ``httpd_config_t.if_name`` to point to a ``struct ifreq`` with ``ifr_name`` populated (for example ``"eth0"``, ``"en0"``, or ``"lo"`` depending on platform).
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
httpd_handle_t server = NULL;
|
||||
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||
|
||||
struct ifreq ifr = {0};
|
||||
strncpy(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name) - 1);
|
||||
ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
|
||||
|
||||
config.if_name = 𝔦
|
||||
config.server_port = 80;
|
||||
|
||||
ESP_ERROR_CHECK(httpd_start(&server, &config));
|
||||
|
||||
Notes:
|
||||
|
||||
- ``if_name`` is only used during ``httpd_start()``. The ``ifreq`` object only needs to stay valid for the duration of that call.
|
||||
|
||||
Persistent Connections
|
||||
----------------------
|
||||
|
||||
HTTP server features persistent connections, allowing for the reuse of the same connection (session) for several transfers, all the while maintaining context specific data for the session. Context data may be allocated dynamically by the handler in which case a custom function may need to be specified for freeing this data when the connection/session is closed.
|
||||
|
||||
Persistent Connections Example
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* Custom function to free context */
|
||||
void free_ctx_func(void *ctx)
|
||||
{
|
||||
/* Could be something other than free */
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
esp_err_t adder_post_handler(httpd_req_t *req)
|
||||
{
|
||||
/* Create session's context if not already available */
|
||||
if (! req->sess_ctx) {
|
||||
req->sess_ctx = malloc(sizeof(ANY_DATA_TYPE)); /*!< Pointer to context data */
|
||||
req->free_ctx = free_ctx_func; /*!< Function to free context data */
|
||||
}
|
||||
|
||||
/* Access context data */
|
||||
ANY_DATA_TYPE *ctx_data = (ANY_DATA_TYPE *)req->sess_ctx;
|
||||
|
||||
/* Respond */
|
||||
...............
|
||||
...............
|
||||
...............
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
Check the example under :example:`protocols/http_server/persistent_sockets`. This example demonstrates how to set up and use an HTTP server with persistent sockets, allowing for independent sessions or contexts per client.
|
||||
|
||||
|
||||
WebSocket Server
|
||||
----------------
|
||||
|
||||
The HTTP server component provides WebSocket support. The WebSocket feature can be enabled in menuconfig using the :ref:`CONFIG_HTTPD_WS_SUPPORT` option.
|
||||
|
||||
:example:`protocols/http_server/ws_echo_server` demonstrates how to create a WebSocket echo server using the HTTP server, which starts on a local network and requires a WebSocket client for interaction, echoing back received WebSocket frames.
|
||||
|
||||
|
||||
WebSocket Pre-Handshake Callback
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The HTTP server component provides a pre-handshake callback for WebSocket endpoints. This callback is invoked before the WebSocket handshake is processed—at this point, the connection is still an HTTP connection and has not yet been upgraded to WebSocket.
|
||||
|
||||
The pre-handshake callback can be used for authentication, authorization, or other checks. If the callback returns :c:macro:`ESP_OK`, the WebSocket handshake will proceed. If the callback returns any other value, the handshake will be aborted and the connection will be closed.
|
||||
|
||||
To use the WebSocket pre-handshake callback, you must enable :ref:`CONFIG_HTTPD_WS_PRE_HANDSHAKE_CB_SUPPORT` in your project configuration.
|
||||
|
||||
WebSocket Post-Handshake Callback
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Similar to the pre-handshake callback, the HTTP server component also provides a post-handshake callback for WebSocket endpoints. This callback is invoked after the WebSocket handshake is processed.
|
||||
|
||||
At this point the connection has been upgraded to WebSocket, and the server has responded with the WebSocket handshake response. This post handshake callback can be used for logging, sending initial messages, or other setup tasks.
|
||||
|
||||
To use the WebSocket post-handshake callback, you must enable :ref:`CONFIG_HTTPD_WS_POST_HANDSHAKE_CB_SUPPORT` in your project configuration.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
static esp_err_t ws_auth_handler(httpd_req_t *req)
|
||||
{
|
||||
// Your authentication logic here
|
||||
// return ESP_OK to allow the handshake, or another value to reject.
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Registering a WebSocket URI handler with pre-handshake authentication
|
||||
static const httpd_uri_t ws = {
|
||||
.uri = "/ws",
|
||||
.method = HTTP_GET,
|
||||
.handler = handler, // Your WebSocket data handler
|
||||
.user_ctx = NULL,
|
||||
.is_websocket = true,
|
||||
.ws_pre_handshake_cb = ws_auth_handler // Set the pre-handshake callback
|
||||
};
|
||||
|
||||
// Register the handler after starting the server:
|
||||
httpd_register_uri_handler(server, &ws);
|
||||
|
||||
|
||||
Event Handling
|
||||
--------------
|
||||
|
||||
ESP HTTP server has various events for which a handler can be triggered by :doc:`the Event Loop library <../system/esp_event>` when the particular event occurs. The handler has to be registered using :cpp:func:`esp_event_handler_register`. This helps in event handling for ESP HTTP server.
|
||||
|
||||
:cpp:enum:`esp_http_server_event_id_t` has all the events which can happen for ESP HTTP server.
|
||||
|
||||
Expected data type for different ESP HTTP server events in event loop:
|
||||
|
||||
- HTTP_SERVER_EVENT_ERROR : ``httpd_err_code_t``
|
||||
- HTTP_SERVER_EVENT_START : ``NULL``
|
||||
- HTTP_SERVER_EVENT_ON_CONNECTED : ``int``
|
||||
- HTTP_SERVER_EVENT_ON_HEADER : ``int``
|
||||
- HTTP_SERVER_EVENT_HEADERS_SENT : ``int``
|
||||
- HTTP_SERVER_EVENT_ON_DATA : ``esp_http_server_event_data``
|
||||
- HTTP_SERVER_EVENT_SENT_DATA : ``esp_http_server_event_data``
|
||||
- HTTP_SERVER_EVENT_DISCONNECTED : ``int``
|
||||
- HTTP_SERVER_EVENT_STOP : ``NULL``
|
||||
|
||||
File Serving
|
||||
------------
|
||||
|
||||
:example:`protocols/http_server/file_serving` demonstrates how to create a simple HTTP file server, with both upload and download capabilities.
|
||||
|
||||
Captive Portal
|
||||
--------------
|
||||
|
||||
:example:`protocols/http_server/captive_portal` demonstrates two methods of creating a captive portal, which directs users to an authentication page before browsing, using either DNS queries and HTTP requests redirection or a modern method involving a field in the DHCP offer.
|
||||
|
||||
Asynchronous Handlers
|
||||
---------------------
|
||||
|
||||
:example:`protocols/http_server/async_handlers` demonstrates how to handle multiple long-running simultaneous requests within the HTTP server, using different URIs for asynchronous requests, quick requests, and the index page.
|
||||
|
||||
RESTful API
|
||||
-----------
|
||||
|
||||
:example:`protocols/http_server/restful_server` demonstrates how to implement a RESTful API server and web server, with a modern frontend UI, and designs several APIs to fetch resources, using mDNS to parse the domain name, and deploying the webpage to SPI flash.
|
||||
|
||||
URI Handlers
|
||||
------------
|
||||
|
||||
The HTTP server allows you to register URI handlers to handle different HTTP requests. Each URI handler is associated with a specific URI and HTTP method (GET, POST, etc.). The handler function is called whenever a request matching the URI and method is received.
|
||||
|
||||
The handler function should return an :cpp:type:`esp_err_t` value.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
esp_err_t my_uri_handler(httpd_req_t *req)
|
||||
{
|
||||
// Handle the request
|
||||
// ...
|
||||
|
||||
// Return ESP_OK if the request was handled successfully
|
||||
return ESP_OK;
|
||||
|
||||
// Return an error code to close the connection
|
||||
// return ESP_FAIL;
|
||||
}
|
||||
|
||||
void register_uri_handlers(httpd_handle_t server)
|
||||
{
|
||||
httpd_uri_t my_uri = {
|
||||
.uri = "/my_uri",
|
||||
.method = HTTP_GET,
|
||||
.handler = my_uri_handler,
|
||||
.user_ctx = NULL
|
||||
};
|
||||
|
||||
httpd_register_uri_handler(server, &my_uri);
|
||||
}
|
||||
|
||||
In this example, the `my_uri_handler` function handles requests to the `/my_uri` URI. If the handler returns :c:macro:`ESP_OK`, the connection remains open. If it returns any other value, the connection is closed. This behavior allows the application to manage connection closure based on specific events or conditions.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
.. include-build-file:: inc/esp_http_server.inc
|
||||
@@ -0,0 +1,100 @@
|
||||
HTTPS Server
|
||||
============
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
This component is built on top of :doc:`esp_http_server`. The HTTPS server takes advantage of hook registration functions in the regular HTTP server to provide callback function for SSL session.
|
||||
|
||||
All documentation for :doc:`esp_http_server` applies also to a server you create this way.
|
||||
|
||||
Used APIs
|
||||
---------
|
||||
|
||||
The following APIs of :doc:`esp_http_server` should not be used with :doc:`esp_https_server`, as they are used internally to handle secure sessions and to maintain internal state:
|
||||
|
||||
* "send", "receive" and "pending" callback registration functions - secure socket handling
|
||||
|
||||
* :cpp:func:`httpd_sess_set_send_override`
|
||||
* :cpp:func:`httpd_sess_set_recv_override`
|
||||
* :cpp:func:`httpd_sess_set_pending_override`
|
||||
|
||||
* "transport context" - both global and session
|
||||
|
||||
* :cpp:func:`httpd_sess_get_transport_ctx` - returns SSL used for the session
|
||||
* :cpp:func:`httpd_sess_set_transport_ctx`
|
||||
* :cpp:func:`httpd_get_global_transport_ctx` - returns the shared SSL context
|
||||
* :cpp:member:`httpd_config::global_transport_ctx`
|
||||
* :cpp:member:`httpd_config::global_transport_ctx_free_fn`
|
||||
* :cpp:member:`httpd_config::open_fn` - used to set up secure sockets
|
||||
|
||||
Everything else can be used without limitations.
|
||||
|
||||
.. note:: APIs in the HTTPS server are not thread-safe. If thread safety is required, it is the responsibility of the application layer to ensure proper synchronization between multiple tasks.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Please see the example :example:`protocols/https_server` to learn how to set up a secure server.
|
||||
|
||||
Basically, all you need is to generate a certificate, embed it into the firmware, and pass the init struct into the start function after the certificate address and lengths are correctly configured in the init struct.
|
||||
|
||||
The server can be started with or without SSL by changing a flag in the init struct - :cpp:member:`httpd_ssl_config::transport_mode`. This could be used, e.g., for testing or in trusted environments where you prefer speed over security.
|
||||
|
||||
Performance
|
||||
-----------
|
||||
|
||||
The initial session setup can take about two seconds, or more with slower clock speed or more verbose logging. Subsequent requests through the open secure socket are much faster (down to under 100 ms).
|
||||
|
||||
Event Handling
|
||||
--------------
|
||||
|
||||
ESP HTTPS Server has various events for which a handler can be triggered by the :doc:`../system/esp_event` when the particular event occurs. The handler has to be registered using :cpp:func:`esp_event_handler_register`. This helps in event handling for ESP HTTPS Server.
|
||||
|
||||
:cpp:enum:`esp_https_server_event_id_t` has all the events which can happen for ESP HTTPS server.
|
||||
|
||||
Expected data type for different ESP HTTPS server events in event loop:
|
||||
|
||||
- HTTPS_SERVER_EVENT_ERROR : ``esp_https_server_last_error_t``
|
||||
- HTTPS_SERVER_EVENT_START : ``NULL``
|
||||
- HTTPS_SERVER_EVENT_ON_CONNECTED : ``NULL``
|
||||
- HTTPS_SERVER_EVENT_ON_DATA : ``int``
|
||||
- HTTPS_SERVER_EVENT_SENT_DATA : ``NULL``
|
||||
- HTTPS_SERVER_EVENT_DISCONNECTED : ``NULL``
|
||||
- HTTPS_SERVER_EVENT_STOP : ``NULL``
|
||||
|
||||
Application Examples
|
||||
--------------------
|
||||
|
||||
- :example:`protocols/https_server/simple` demonstrates how to create an HTTPS server that returns a simple HTML page when visited.
|
||||
|
||||
- :example:`protocols/https_server/wss_server` demonstrates how to create an SSL server with a simple WebSocket request handler that supports handling multiple clients, PING-PONG mechanism, and sending asynchronous messages to all clients.
|
||||
|
||||
HTTPS Server Cert Selection Hook
|
||||
--------------------------------
|
||||
|
||||
The ESP HTTPS Server component provides an option to set the server certification selection hook. This feature allows you to configure and use a certificate selection callback during server handshake. The callback helps to select a certificate to present to the client based on the TLS extensions supplied in the client hello message, such as ALPN and SNI.
|
||||
|
||||
To enable this feature, please enable :ref:`CONFIG_ESP_HTTPS_SERVER_CERT_SELECT_HOOK` in the ESP HTTPS Server menuconfig. Please note that the ESP-TLS option is only available when Mbedtls is used as the TLS stack for ESP-TLS (default behaviour).
|
||||
|
||||
When enabled, you can set the certificate selection callback using the :cpp:member:`httpd_ssl_config::cert_select_cb` member of the :cpp:type:`httpd_ssl_config_t` structure.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
int cert_selection_callback(mbedtls_ssl_context *ssl)
|
||||
{
|
||||
/* Code that the callback should execute */
|
||||
return 0;
|
||||
}
|
||||
|
||||
httpd_ssl_config_t cfg = {
|
||||
cert_select_cb = cert_section_callback,
|
||||
};
|
||||
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
.. include-build-file:: inc/esp_https_server.inc
|
||||
@@ -0,0 +1,219 @@
|
||||
ESP Local Control
|
||||
=================
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
ESP Local Control (**esp_local_ctrl**) component in ESP-IDF provides capability to control an ESP device over HTTPS or Bluetooth® Low Energy. It provides access to application defined **properties** that are available for reading/writing via a set of configurable handlers.
|
||||
|
||||
.. only:: SOC_BT_SUPPORTED
|
||||
|
||||
Initialization of the **esp_local_ctrl** service over Bluetooth Low Energy transport is performed as follows:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
esp_local_ctrl_config_t config = {
|
||||
.transport = ESP_LOCAL_CTRL_TRANSPORT_BLE,
|
||||
.transport_config = {
|
||||
.ble = & (protocomm_ble_config_t) {
|
||||
.device_name = SERVICE_NAME,
|
||||
.service_uuid = {
|
||||
/* LSB <---------------------------------------
|
||||
* ---------------------------------------> MSB */
|
||||
0x21, 0xd5, 0x3b, 0x8d, 0xbd, 0x75, 0x68, 0x8a,
|
||||
0xb4, 0x42, 0xeb, 0x31, 0x4a, 0x1e, 0x98, 0x3d
|
||||
}
|
||||
}
|
||||
},
|
||||
.proto_sec = {
|
||||
.version = PROTOCOM_SEC0,
|
||||
.custom_handle = NULL,
|
||||
.sec_params = NULL,
|
||||
},
|
||||
.handlers = {
|
||||
/* User defined handler functions */
|
||||
.get_prop_values = get_property_values,
|
||||
.set_prop_values = set_property_values,
|
||||
.usr_ctx = NULL,
|
||||
.usr_ctx_free_fn = NULL
|
||||
},
|
||||
/* Maximum number of properties that may be set */
|
||||
.max_properties = 10
|
||||
};
|
||||
|
||||
/* Start esp_local_ctrl service */
|
||||
ESP_ERROR_CHECK(esp_local_ctrl_start(&config));
|
||||
|
||||
|
||||
Initialization of the **esp_local_ctrl** service over HTTPS transport is performed as follows:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* Set the configuration */
|
||||
httpd_ssl_config_t https_conf = HTTPD_SSL_CONFIG_DEFAULT();
|
||||
|
||||
/* Load server certificate */
|
||||
extern const unsigned char servercert_start[] asm("_binary_servercert_pem_start");
|
||||
extern const unsigned char servercert_end[] asm("_binary_servercert_pem_end");
|
||||
https_conf.servercert = servercert_start;
|
||||
https_conf.servercert_len = servercert_end - servercert_start;
|
||||
|
||||
/* Load server private key */
|
||||
extern const unsigned char prvtkey_pem_start[] asm("_binary_prvtkey_pem_start");
|
||||
extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end");
|
||||
https_conf.prvtkey_pem = prvtkey_pem_start;
|
||||
https_conf.prvtkey_len = prvtkey_pem_end - prvtkey_pem_start;
|
||||
|
||||
esp_local_ctrl_config_t config = {
|
||||
.transport = ESP_LOCAL_CTRL_TRANSPORT_HTTPD,
|
||||
.transport_config = {
|
||||
.httpd = &https_conf
|
||||
},
|
||||
.proto_sec = {
|
||||
.version = PROTOCOM_SEC0,
|
||||
.custom_handle = NULL,
|
||||
.sec_params = NULL,
|
||||
},
|
||||
.handlers = {
|
||||
/* User defined handler functions */
|
||||
.get_prop_values = get_property_values,
|
||||
.set_prop_values = set_property_values,
|
||||
.usr_ctx = NULL,
|
||||
.usr_ctx_free_fn = NULL
|
||||
},
|
||||
/* Maximum number of properties that may be set */
|
||||
.max_properties = 10
|
||||
};
|
||||
|
||||
/* Start esp_local_ctrl service */
|
||||
ESP_ERROR_CHECK(esp_local_ctrl_start(&config));
|
||||
|
||||
You may set security for transport in ESP local control using following options:
|
||||
|
||||
1. ``PROTOCOM_SEC2``: specifies that SRP6a-based key exchange and end-to-end encryption based on AES-GCM are used. This is the most preferred option as it adds a robust security with Augmented PAKE protocol, i.e., SRP6a.
|
||||
2. ``PROTOCOM_SEC1``: specifies that Curve25519-based key exchange and end-to-end encryption based on AES-CTR are used.
|
||||
3. ``PROTOCOM_SEC0``: specifies that data will be exchanged as a plain text (no security).
|
||||
4. ``PROTOCOM_SEC_CUSTOM``: you can define your own security requirement. Please note that you will also have to provide ``custom_handle`` of type ``protocomm_security_t *`` in this context.
|
||||
|
||||
.. warning::
|
||||
It is strongly recommended to use ``PROTOCOM_SEC2`` for production deployments. ``PROTOCOM_SEC0`` provides no encryption or authentication, leaving device properties exposed to any client on the local network. ``PROTOCOM_SEC1`` provides weaker security compared to ``PROTOCOM_SEC2`` and its use is discouraged for new designs.
|
||||
|
||||
.. note::
|
||||
The respective security schemes need to be enabled through the project configuration menu. Please refer to the Enabling protocom security version section in :doc:`Protocol Communication </api-reference/provisioning/protocomm>` for more details.
|
||||
|
||||
Creating a Property
|
||||
-------------------
|
||||
|
||||
Now that we know how to start the **esp_local_ctrl** service, let's add a property to it. Each property must have a unique ``name`` (string), a ``type`` (e.g., enum), ``flags`` (bit fields) and ``size``.
|
||||
|
||||
The ``size`` is to be kept 0, if we want our property value to be of variable length (e.g., if it is a string or bytestream). For data types with fixed-length property value, like int, float, etc., setting the ``size`` field to the right value helps **esp_local_ctrl** to perform internal checks on arguments received with write requests.
|
||||
|
||||
The interpretation of ``type`` and ``flags`` fields is totally upto the application, hence they may be used as enumerations, bitfields, or even simple integers. One way is to use ``type`` values to classify properties, while ``flags`` to specify characteristics of a property.
|
||||
|
||||
Here is an example property which is to function as a timestamp. It is assumed that the application defines ``TYPE_TIMESTAMP`` and ``READONLY``, which are used for setting the ``type`` and ``flags`` fields here.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* Create a timestamp property */
|
||||
esp_local_ctrl_prop_t timestamp = {
|
||||
.name = "timestamp",
|
||||
.type = TYPE_TIMESTAMP,
|
||||
.size = sizeof(int32_t),
|
||||
.flags = READONLY,
|
||||
.ctx = func_get_time,
|
||||
.ctx_free_fn = NULL
|
||||
};
|
||||
|
||||
/* Now register the property */
|
||||
esp_local_ctrl_add_property(×tamp);
|
||||
|
||||
|
||||
Also notice that there is a ctx field, which is set to point to some custom `func_get_time()`. This can be used inside the property get/set handlers to retrieve timestamp.
|
||||
|
||||
Here is an example of ``get_prop_values()`` handler, which is used for retrieving the timestamp.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
static esp_err_t get_property_values(size_t props_count,
|
||||
const esp_local_ctrl_prop_t *props,
|
||||
esp_local_ctrl_prop_val_t *prop_values,
|
||||
void *usr_ctx)
|
||||
{
|
||||
for (uint32_t i = 0; i < props_count; i++) {
|
||||
ESP_LOGI(TAG, "Reading %s", props[i].name);
|
||||
if (props[i].type == TYPE_TIMESTAMP) {
|
||||
/* Obtain the timer function from ctx */
|
||||
int32_t (*func_get_time)(void) = props[i].ctx;
|
||||
|
||||
/* Use static variable for saving the value. This is essential because the value has to be valid even after this function returns. Alternative is to use dynamic allocation and set the free_fn field */
|
||||
static int32_t ts = func_get_time();
|
||||
prop_values[i].data = &ts;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
Here is an example of ``set_prop_values()`` handler. Notice how we restrict from writing to read-only properties.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
static esp_err_t set_property_values(size_t props_count,
|
||||
const esp_local_ctrl_prop_t *props,
|
||||
const esp_local_ctrl_prop_val_t *prop_values,
|
||||
void *usr_ctx)
|
||||
{
|
||||
for (uint32_t i = 0; i < props_count; i++) {
|
||||
if (props[i].flags & READONLY) {
|
||||
ESP_LOGE(TAG, "Cannot write to read-only property %s", props[i].name);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Setting %s", props[i].name);
|
||||
|
||||
/* For keeping it simple, lets only log the incoming data */
|
||||
ESP_LOG_BUFFER_HEX_LEVEL(TAG, prop_values[i].data,
|
||||
prop_values[i].size, ESP_LOG_INFO);
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
For complete example see :example:`protocols/esp_local_ctrl`. The example demonstrates how to set up a secure ``esp_local_ctrl`` service over HTTPS transport for controlling devices on a local network.
|
||||
|
||||
Client Side Implementation
|
||||
--------------------------
|
||||
|
||||
The client side implementation establishes a protocomm session with the device first, over the supported mode of transport, and then send and receive protobuf messages understood by the **esp_local_ctrl** service. The service translates these messages into requests and then call the appropriate handlers (set/get). Then, the generated response for each handler is again packed into a protobuf message and transmitted back to the client.
|
||||
|
||||
See below the various protobuf messages understood by the **esp_local_ctrl** service:
|
||||
|
||||
1. ``get_prop_count`` : This should simply return the total number of properties supported by the service.
|
||||
2. ``get_prop_values`` : This accepts an array of indices and should return the information (name, type, flags) and values of the properties corresponding to those indices.
|
||||
3. ``set_prop_values`` : This accepts an array of indices and an array of new values, which are used for setting the values of the properties corresponding to the indices.
|
||||
|
||||
Note that indices may or may not be the same for a property, across multiple sessions. Therefore, the client must only use the names of the properties to uniquely identify them. So, every time a new session is established, the client should first call ``get_prop_count`` and then ``get_prop_values``, hence form an index-to-name mapping for all properties. Now when calling ``set_prop_values`` for a set of properties, it must first convert the names to indexes, using the created mapping. As emphasized earlier, the client must refresh the index-to-name mapping every time a new session is established with the same device.
|
||||
|
||||
The various protocomm endpoints provided by **esp_local_ctrl** are listed below:
|
||||
|
||||
.. list-table:: Endpoints provided by ESP Local Control
|
||||
:widths: 10 25 50
|
||||
:header-rows: 1
|
||||
|
||||
* - Endpoint Name (Bluetooth Low Energy + GATT Server)
|
||||
- URI (HTTPS Server + mDNS)
|
||||
- Description
|
||||
* - esp_local_ctrl/version
|
||||
- https://<mdns-hostname>.local/esp_local_ctrl/version
|
||||
- Endpoint used for retrieving version string
|
||||
* - esp_local_ctrl/control
|
||||
- https://<mdns-hostname>.local/esp_local_ctrl/control
|
||||
- Endpoint used for sending or receiving control messages
|
||||
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
.. include-build-file:: inc/esp_local_ctrl.inc
|
||||
@@ -0,0 +1,455 @@
|
||||
ESP-TLS
|
||||
=======
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
The ESP-TLS component provides a simplified API interface for accessing the commonly used TLS functions. It supports common scenarios like CA certification validation, SNI, ALPN negotiation, and non-blocking connection among others. All the configurations can be specified in the ``esp_tls_cfg_t`` data structure. Once done, TLS communication can be conducted using the following APIs:
|
||||
|
||||
* :cpp:func:`esp_tls_init`: for initializing the TLS connection handle.
|
||||
* :cpp:func:`esp_tls_conn_new_sync`: for opening a new blocking TLS connection.
|
||||
* :cpp:func:`esp_tls_conn_new_async`: for opening a new non-blocking TLS connection.
|
||||
* :cpp:func:`esp_tls_conn_read`: for reading from the connection.
|
||||
* :cpp:func:`esp_tls_conn_write`: for writing into the connection.
|
||||
* :cpp:func:`esp_tls_conn_destroy`: for freeing up the connection.
|
||||
|
||||
Any application layer protocol like HTTP1, HTTP2, etc can be executed on top of this layer.
|
||||
|
||||
Application Example
|
||||
-------------------
|
||||
|
||||
Simple HTTPS example that uses ESP-TLS to establish a secure socket connection: :example:`protocols/https_request`.
|
||||
|
||||
Tree Structure for ESP-TLS Component
|
||||
-------------------------------------
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
├── esp_tls.c
|
||||
├── esp_tls.h
|
||||
├── esp_tls_mbedtls.c
|
||||
├── esp_tls_custom_stack.c
|
||||
└── private_include
|
||||
├── esp_tls_mbedtls.h
|
||||
└── esp_tls_custom_stack.h
|
||||
|
||||
The ESP-TLS component has a file :component_file:`esp-tls/esp_tls.h` which contains the public API headers for the component. Internally, the ESP-TLS component operates using MbedTLS as the default SSL/TLS library, or a custom TLS stack registered via the :cpp:func:`esp_tls_register_stack` API. APIs specific to MbedTLS are present in :component_file:`esp-tls/private_include/esp_tls_mbedtls.h` and APIs for custom stack registration are present in :component_file:`esp-tls/esp_tls_custom_stack.h`.
|
||||
|
||||
.. _esp_tls_server_verification:
|
||||
|
||||
TLS Server Verification
|
||||
-----------------------
|
||||
|
||||
ESP-TLS provides multiple options for TLS server verification on the client side. The ESP-TLS client can verify the server by validating the peer's server certificate or with the help of pre-shared keys. The user should select only one of the following options in the :cpp:type:`esp_tls_cfg_t` structure for TLS server verification. If no option is selected, the client will return a fatal error by default during the TLS connection setup.
|
||||
|
||||
* **cacert_buf** and **cacert_bytes**: The CA certificate can be provided in a buffer to the :cpp:type:`esp_tls_cfg_t` structure. The ESP-TLS uses the CA certificate present in the buffer to verify the server. The following variables in the :cpp:type:`esp_tls_cfg_t` structure must be set.
|
||||
|
||||
* ``cacert_buf`` - pointer to the buffer which contains the CA certification.
|
||||
* ``cacert_bytes`` - the size of the CA certificate in bytes.
|
||||
* **use_global_ca_store**: The ``global_ca_store`` can be initialized and set at once. Then it can be used to verify the server for all the ESP-TLS connections which have set ``use_global_ca_store = true`` in their respective :cpp:type:`esp_tls_cfg_t` structure. See the API Reference section below for information regarding different APIs used for initializing and setting up the ``global_ca_store``.
|
||||
* **crt_bundle_attach**: The ESP x509 Certificate Bundle API provides an easy way to include a bundle of custom x509 root certificates for TLS server verification. More details can be found at :doc:`ESP x509 Certificate Bundle </api-reference/protocols/esp_crt_bundle>`.
|
||||
* **psk_hint_key**: To use pre-shared keys for server verification, :ref:`CONFIG_ESP_TLS_PSK_VERIFICATION` should be enabled in the ESP-TLS menuconfig. Then the pointer to the PSK hint and key should be provided to the :cpp:type:`esp_tls_cfg_t` structure. The ESP-TLS will use the PSK for server verification only when no other option regarding server verification is selected.
|
||||
* **skip server verification**: This is an insecure option provided in the ESP-TLS for testing purposes. The option can be set by enabling :ref:`CONFIG_ESP_TLS_INSECURE` and :ref:`CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY` in the ESP-TLS menuconfig. When this option is enabled the ESP-TLS will skip server verification by default when no other options for server verification are selected in the :cpp:type:`esp_tls_cfg_t` structure.
|
||||
|
||||
.. warning::
|
||||
|
||||
If this option is enabled, there is a risk of establishing a TLS connection with a server that has a fake identity, unless the server certificate is provided through the API or other mechanisms like ``ca_store``.
|
||||
|
||||
SNI (Server Name Indication)
|
||||
----------------------------
|
||||
|
||||
SNI is an extension to the TLS protocol that allows the client to specify the hostname it is connecting to during the TLS handshake. This is required when connecting to servers that host multiple domains on the same IP address.
|
||||
|
||||
**How to ensure SNI works properly:**
|
||||
|
||||
* SNI is enabled by default in ESP-TLS when using HTTPS connections.
|
||||
* To explicitly set the SNI hostname, use the ``common_name`` field in :cpp:type:`esp_tls_cfg_t`. This ensures that the correct hostname is sent to the server during the handshake.
|
||||
* The value of ``common_name`` must match the server certificate's CN (Common Name).
|
||||
* The ``skip_common_name`` field should be set to ``false`` to ensure the server certificate is properly validated against the hostname. This is required for SNI to function correctly.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
esp_tls_cfg_t cfg = {
|
||||
.cacert_buf = ...,
|
||||
.cacert_bytes = ...,
|
||||
.common_name = "example.com", // SNI hostname
|
||||
.skip_common_name = false, // Ensure certificate is validated
|
||||
};
|
||||
|
||||
ESP-TLS Server Cert Selection Hook
|
||||
----------------------------------
|
||||
|
||||
The ESP-TLS component provides an option to set the server certification selection hook when using the MbedTLS stack. This provides an ability to configure and use a certificate selection callback during server handshake. The callback helps to select a certificate to present to the client based on the TLS extensions supplied in the client hello message, such as ALPN and SNI. To enable this feature, please enable :ref:`CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK` in the ESP-TLS menuconfig.
|
||||
|
||||
The certificate selection callback can be configured in the :cpp:type:`esp_tls_cfg_t` structure as follows:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
int cert_selection_callback(mbedtls_ssl_context *ssl)
|
||||
{
|
||||
/* Code that the callback should execute */
|
||||
return 0;
|
||||
}
|
||||
|
||||
esp_tls_cfg_t cfg = {
|
||||
cert_select_cb = cert_section_callback,
|
||||
};
|
||||
|
||||
.. _esp_tls_custom_stack:
|
||||
|
||||
Custom TLS Stack Support
|
||||
------------------------
|
||||
|
||||
The ESP-TLS component supports registering custom TLS stack implementations via the :cpp:func:`esp_tls_register_stack` API. This allows external components to provide their own TLS stack implementation by implementing the :cpp:type:`esp_tls_stack_ops_t` interface. Once registered, all TLS connections created after the registration will use the custom stack.
|
||||
|
||||
.. note::
|
||||
|
||||
As the custom stack implementation is internal to ESP-TLS, switching to a custom stack will not change ESP-TLS specific code for a project.
|
||||
|
||||
How to Use Custom TLS Stack with ESP-IDF
|
||||
----------------------------------------
|
||||
|
||||
To use a custom TLS stack in your project, follow these steps:
|
||||
|
||||
1. Enable the custom stack option ``CONFIG_ESP_TLS_CUSTOM_STACK`` (Component config > ESP-TLS > SSL/TLS Library > Custom TLS stack) in menuconfig.
|
||||
|
||||
2. Implement all required functions defined in the :cpp:type:`esp_tls_stack_ops_t` structure. The required functions are:
|
||||
|
||||
* ``create_ssl_handle`` - Initialize TLS/SSL context for a new connection
|
||||
* ``handshake`` - Perform TLS handshake
|
||||
* ``read`` - Read decrypted data from TLS connection
|
||||
* ``write`` - Write and encrypt data to TLS connection
|
||||
* ``conn_delete`` - Clean up TLS connection and free resources
|
||||
* ``net_init`` - Initialize network context
|
||||
* ``get_ssl_context`` - Get stack-specific SSL context
|
||||
* ``get_bytes_avail`` - Get bytes available for reading
|
||||
* ``init_global_ca_store`` - Initialize global CA store
|
||||
* ``set_global_ca_store`` - Load CA certificates into global store
|
||||
* ``get_global_ca_store`` - Get global CA store
|
||||
* ``free_global_ca_store`` - Free global CA store
|
||||
* ``get_ciphersuites_list`` - Get list of supported ciphersuites
|
||||
|
||||
Optional functions (can be NULL if not supported):
|
||||
|
||||
* ``get_client_session`` - Get client session ticket (if CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS enabled)
|
||||
* ``free_client_session`` - Free client session (if CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS enabled)
|
||||
* ``server_session_ticket_ctx_init`` - Initialize server session ticket context (if CONFIG_ESP_TLS_SERVER_SESSION_TICKETS enabled)
|
||||
* ``server_session_ticket_ctx_free`` - Free server session ticket context (if CONFIG_ESP_TLS_SERVER_SESSION_TICKETS enabled)
|
||||
* ``server_session_create`` - Create server session (server-side, can be NULL if server_session_init is provided)
|
||||
* ``server_session_init`` - Initialize server session (server-side, can be NULL if server_session_create is provided)
|
||||
* ``server_session_continue_async`` - Continue async server handshake (server-side, can be NULL if server_session_create is provided)
|
||||
* ``server_session_delete`` - Delete server session (server-side, can be NULL, conn_delete will be used)
|
||||
|
||||
3. Create a static/global structure containing your function implementations:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include "esp_tls_custom_stack.h"
|
||||
|
||||
static const esp_tls_stack_ops_t my_tls_ops = {
|
||||
.version = ESP_TLS_STACK_OPS_VERSION,
|
||||
.create_ssl_handle = my_create_ssl_handle,
|
||||
.handshake = my_handshake,
|
||||
.read = my_read,
|
||||
.write = my_write,
|
||||
.conn_delete = my_conn_delete,
|
||||
.net_init = my_net_init,
|
||||
.get_ssl_context = my_get_ssl_context,
|
||||
.get_bytes_avail = my_get_bytes_avail,
|
||||
.init_global_ca_store = my_init_global_ca_store,
|
||||
.set_global_ca_store = my_set_global_ca_store,
|
||||
.get_global_ca_store = my_get_global_ca_store,
|
||||
.free_global_ca_store = my_free_global_ca_store,
|
||||
.get_ciphersuites_list = my_get_ciphersuites_list,
|
||||
// Optional functions can be NULL if not supported
|
||||
.get_client_session = NULL,
|
||||
.free_client_session = NULL,
|
||||
.server_session_ticket_ctx_init = NULL,
|
||||
.server_session_ticket_ctx_free = NULL,
|
||||
.server_session_create = NULL,
|
||||
.server_session_init = NULL,
|
||||
.server_session_continue_async = NULL,
|
||||
.server_session_delete = NULL,
|
||||
};
|
||||
|
||||
4. Register your custom stack before creating any TLS connections:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
void app_main(void) {
|
||||
// The second parameter is user context passed to global callbacks
|
||||
// (init_global_ca_store, set_global_ca_store, etc.)
|
||||
// Use NULL if not needed, or pass a pointer for C++ implementations
|
||||
esp_err_t ret = esp_tls_register_stack(&my_tls_ops, NULL);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE("APP", "Failed to register TLS stack: %s", esp_err_to_name(ret));
|
||||
return;
|
||||
}
|
||||
|
||||
// Now all TLS connections will use your custom stack
|
||||
// ... create TLS connections as usual using esp_tls_conn_new(), etc. ...
|
||||
}
|
||||
|
||||
.. important::
|
||||
|
||||
* The custom stack must be registered **before** creating any TLS connections. Calling :cpp:func:`esp_tls_register_stack` after TLS connections have been created will not affect existing connections.
|
||||
* The :cpp:type:`esp_tls_stack_ops_t` structure must point to a static/global structure (not on the stack) as it's stored by reference.
|
||||
* Your implementation should store stack-specific context data in the ``priv_ctx`` and ``priv_ssl`` fields of the :cpp:type:`esp_tls_t` structure.
|
||||
* All required function pointers must be non-NULL. Optional functions can be NULL if not supported.
|
||||
* The registration function can only be called once. Subsequent calls will return ``ESP_ERR_INVALID_STATE``.
|
||||
* For detailed function signatures and requirements, see :component_file:`esp-tls/esp_tls_custom_stack.h`.
|
||||
|
||||
|
||||
.. _atecc608a-with-esp-tls:
|
||||
|
||||
ATECC608A (Secure Element) with ESP-TLS
|
||||
--------------------------------------------------
|
||||
|
||||
ESP-TLS provides support for using ATECC608A cryptoauth chip with ESP32 series of SoCs via the PSA Crypto opaque driver interface. The use of ATECC608A is supported only when ESP-TLS is used with MbedTLS as its underlying SSL/TLS stack. ESP-TLS uses MbedTLS as its underlying TLS/SSL stack by default unless changed manually.
|
||||
|
||||
.. note::
|
||||
|
||||
ATECC608A chip interfaced to ESP32 series must be already configured. For details, please refer to `esp_cryptoauth_utility <https://github.com/espressif/esp-cryptoauthlib/blob/master/esp_cryptoauth_utility/README.md#esp_cryptoauth_utility>`_.
|
||||
|
||||
To enable the secure element support, and use it in your project for TLS connection, follow the steps below:
|
||||
|
||||
1) Add `esp-cryptoauthlib <https://github.com/espressif/esp-cryptoauthlib>`_ as a dependency in your project. For details, please refer to `how to use esp-cryptoauthlib with ESP-IDF <https://github.com/espressif/esp-cryptoauthlib#how-to-use-esp-cryptoauthlib-with-esp-idf>`_.
|
||||
|
||||
2) Enable the menuconfig option :ref:`CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED`:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
menuconfig > Component config > mbedTLS > Enable secure element hardware support
|
||||
|
||||
3) Select the type of ATECC608A chip:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
menuconfig > Component config > esp-cryptoauthlib > Choose Type of ATECC608A chip
|
||||
|
||||
To know more about different types of ATECC608A chips and how to obtain the type of ATECC608A connected to your ESP module, please visit `ATECC608A chip type <https://github.com/espressif/esp-cryptoauthlib/blob/master/esp_cryptoauth_utility/README.md#find-type-of-atecc608a-chip-connected-to-esp32-wroom32-se>`_.
|
||||
|
||||
4) Import the ATECC608A key and configure ESP-TLS to use it via :cpp:type:`esp_key_config_t`:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include "psa/crypto.h"
|
||||
#include "psa_crypto_driver_secure_element.h"
|
||||
#include "psa_crypto_driver_secure_element_contexts.h"
|
||||
#include "esp_key_config.h"
|
||||
|
||||
/* Import ATECC608A key reference into PSA */
|
||||
psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
|
||||
psa_set_key_lifetime(&key_attr, PSA_KEY_LIFETIME_SECURE_ELEMENT_VOLATILE);
|
||||
psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_HASH);
|
||||
psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
|
||||
psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
|
||||
psa_set_key_bits(&key_attr, 256);
|
||||
|
||||
secure_element_opaque_key_t opaque_key = {
|
||||
.slot_id = 0, /* Private key slot on ATECC608A */
|
||||
};
|
||||
|
||||
psa_key_id_t psa_key_id;
|
||||
psa_status_t status = psa_import_key(&key_attr, (const uint8_t *)&opaque_key,
|
||||
sizeof(opaque_key), &psa_key_id);
|
||||
if (status != PSA_SUCCESS) {
|
||||
/* Handle error - typically means the SE callbacks are not registered
|
||||
* or the attributes are invalid. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Configure ESP-TLS to use the PSA key */
|
||||
esp_key_config_t key_config = {
|
||||
.source = ESP_KEY_SOURCE_PSA,
|
||||
.psa.key_id = psa_key_id,
|
||||
};
|
||||
|
||||
esp_tls_cfg_t cfg = {
|
||||
/* other configuration options */
|
||||
.client_key = &key_config,
|
||||
};
|
||||
|
||||
.. only:: SOC_DIG_SIGN_SUPPORTED
|
||||
|
||||
.. _digital-signature-with-esp-tls:
|
||||
|
||||
Digital Signature with ESP-TLS
|
||||
------------------------------
|
||||
|
||||
ESP-TLS provides support for using the RSA Digital Signature Peripheral (RSA_DS) with {IDF_TARGET_NAME}. Use of the RSA_DS for TLS is supported only when ESP-TLS is used with MbedTLS (default stack) as its underlying SSL/TLS stack. For more details on the RSA_DS, please refer to the :doc:`RSA Digital Signature Peripheral (RSA_DS) </api-reference/peripherals/ds>`. The technical details such as how to calculate private key parameters can be found in **{IDF_TARGET_NAME} Technical Reference Manual** > **RSA Digital Signature Peripheral (RSA_DS)** [`PDF <{IDF_TARGET_TRM_EN_URL}#digsig>`__]. The RSA_DS peripheral must be configured before it can be used to perform RSA digital signature, see :ref:`configure-the-ds-peripheral`.
|
||||
|
||||
The RSA_DS peripheral must be initialized with the required encrypted private key parameters, which are obtained when the RSA_DS peripheral is configured. ESP-TLS internally initializes the RSA_DS peripheral when provided with the required DS context, i.e., DS parameters. Please see the below code snippet for passing the DS context to the ESP-TLS context. The DS context passed to the ESP-TLS context should not be freed till the TLS connection is deleted.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include "esp_tls.h"
|
||||
esp_ds_data_ctx_t *ds_ctx;
|
||||
/* initialize ds_ctx with encrypted private key parameters, which can be read from the nvs or provided through the application code */
|
||||
esp_tls_cfg_t cfg = {
|
||||
.clientcert_buf = /* the client certification */,
|
||||
.clientcert_bytes = /* length of the client certification */,
|
||||
/* other configurations options */
|
||||
.ds_data = (void *)ds_ctx,
|
||||
};
|
||||
|
||||
.. note::
|
||||
|
||||
When using the RSA_DS for the TLS connection, along with the other required params, only the client certification (`clientcert_buf`) and the DS params (`ds_data`) are required and the client key (`clientkey_buf`) can be set to NULL.
|
||||
|
||||
* A mutual-authentication example that utilizes the RSA_DS peripheral is shipped with the standalone `espressif/mqtt <https://components.espressif.com/components/espressif/mqtt>`__ component and internally relies on ESP-TLS for the TLS connection. Follow the component documentation to fetch and build that example.
|
||||
|
||||
.. only:: SOC_ECDSA_SUPPORTED
|
||||
|
||||
.. _ecdsa-peri-with-esp-tls:
|
||||
|
||||
ECDSA Digital Signature Peripheral (ECDSA_DS) with ESP-TLS
|
||||
-----------------------------------------------------------
|
||||
|
||||
ESP-TLS provides support for using the ECDSA Digital Signature Peripheral (ECDSA_DS) with {IDF_TARGET_NAME}. The use of the ECDSA_DS peripheral is supported only when ESP-TLS is used with MbedTLS as its underlying SSL/TLS stack. The ECDSA private key should be present in the eFuse for using the ECDSA_DS peripheral. Please refer to :doc:`ECDSA Digital Signature Peripheral (ECDSA_DS) <../peripherals/ecdsa>` for programming the ECDSA key in the eFuse.
|
||||
|
||||
This will enable the use of the ECDSA_DS peripheral for private key operations. As the client private key is already present in the eFuse, it need not be supplied to the :cpp:type:`esp_tls_cfg_t` structure. Please see the below code snippet for enabling the use of the ECDSA_DS peripheral for a given ESP-TLS connection.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include "esp_tls.h"
|
||||
esp_tls_cfg_t cfg = {
|
||||
.use_ecdsa_peripheral = true,
|
||||
.ecdsa_key_efuse_blk = 4, // Low eFuse block for ECDSA key
|
||||
.ecdsa_key_efuse_blk_high = 5, // High eFuse block for ECDSA key (SECP384R1 only)
|
||||
.ecdsa_curve = ESP_TLS_ECDSA_CURVE_SECP384R1, // set this to ESP_TLS_ECDSA_CURVE_SECP256R1 for SECP256R1 curve
|
||||
};
|
||||
|
||||
.. note::
|
||||
|
||||
When using the ECDSA_DS peripheral with TLS, only ``MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256`` ciphersuite is supported. If using TLS v1.3, ``MBEDTLS_TLS1_3_AES_128_GCM_SHA256`` ciphersuite is supported.
|
||||
|
||||
|
||||
.. _esp_tls_client_session_tickets:
|
||||
|
||||
Client Session Tickets
|
||||
----------------------
|
||||
|
||||
ESP-TLS supports client-side session resumption, which can significantly reduce the time and resources spent on full TLS handshakes for subsequent connections to the same server. This feature is available when ESP-TLS uses MbedTLS as its underlying SSL/TLS stack.
|
||||
|
||||
The mechanism for session resumption differs slightly between TLS versions:
|
||||
|
||||
* **TLS 1.2**: Session resumption can be achieved using session IDs (managed internally by the TLS stack) or session tickets (as per `RFC 5077 <https://tools.ietf.org/html/rfc5077>`_). ESP-TLS focuses on the session ticket mechanism for explicit application control.
|
||||
* **TLS 1.3**: Session resumption is accomplished exclusively through session tickets, which are sent by the server via a "NewSessionTicket" message after the main handshake is complete. Unlike TLS 1.2, these tickets can be sent at any time during the session, not just immediately after the handshake.
|
||||
|
||||
To enable and use client session tickets:
|
||||
|
||||
1. Enable the Kconfig option :ref:`CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS`.
|
||||
2. After a successful TLS connection (and handshake completion), retrieve the session ticket using :cpp:func:`esp_tls_get_client_session`.
|
||||
|
||||
* **For TLS 1.3**: Since session tickets can arrive from the server at any point after the handshake, an application might need to call :cpp:func:`esp_tls_get_client_session` periodically or after specific application-level exchanges if it wants to ensure it has the most recent ticket. Each new ticket received and processed by the TLS stack supersedes the previous one for future resumption attempts.
|
||||
|
||||
3. Store this session ticket securely.
|
||||
4. For subsequent connections to the same server, provide the stored session ticket in the :cpp:member:`esp_tls_cfg_t::client_session` field.
|
||||
5. Remember to free the client session context using :cpp:func:`esp_tls_free_client_session` when it's no longer needed or before obtaining a new one.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include "esp_tls.h"
|
||||
|
||||
// Global or persistent storage for the client session
|
||||
esp_tls_client_session_t *saved_session = NULL;
|
||||
|
||||
void connect_to_server(bool use_saved_session_arg) {
|
||||
esp_tls_cfg_t cfg = {0}; // Initialize other config parameters as needed
|
||||
// ... set other cfg members like cacert_buf, common_name etc. ...
|
||||
|
||||
if (use_saved_session_arg && saved_session) {
|
||||
cfg.client_session = saved_session;
|
||||
// ESP_LOGI(TAG, "Attempting connection with saved session ticket.");
|
||||
} else {
|
||||
// ESP_LOGI(TAG, "Attempting connection without a saved session ticket (full handshake).");
|
||||
}
|
||||
|
||||
esp_tls_t *tls = esp_tls_init();
|
||||
if (!tls) {
|
||||
// ESP_LOGE(TAG, "Failed to initialize ESP-TLS handle.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (esp_tls_conn_http_new_sync("https://your-server.com", &cfg, tls) == 1) {
|
||||
// ESP_LOGI(TAG, "Connection successful.");
|
||||
|
||||
// Always try to get/update the session ticket to have the latest one.
|
||||
// This is beneficial whether the connection was a new handshake or a resumption,
|
||||
// especially for TLS 1.3 where new tickets can arrive post-handshake.
|
||||
if (saved_session) {
|
||||
esp_tls_free_client_session(saved_session); // Free previous session if any
|
||||
saved_session = NULL;
|
||||
}
|
||||
saved_session = esp_tls_get_client_session(tls);
|
||||
if (saved_session) {
|
||||
// ESP_LOGI(TAG, "Successfully retrieved/updated client session ticket.");
|
||||
} else {
|
||||
// ESP_LOGW(TAG, "Failed to get client session ticket even after a successful connection.");
|
||||
}
|
||||
|
||||
// ... do TLS communication ...
|
||||
|
||||
}
|
||||
esp_tls_conn_destroy(tls);
|
||||
}
|
||||
|
||||
.. note::
|
||||
|
||||
- The session ticket obtained from a server is typically valid for a limited time. The server dictates this lifetime.
|
||||
- When attempting a connection using a stored session ticket, if the ticket is found to be invalid by the server (e.g., it has expired or is otherwise rejected), ESP-TLS will automatically attempt to perform a full TLS handshake to establish the connection. The application does not need to implement separate logic to retry the connection without the ticket in this scenario. A connection failure will only be reported if both the session resumption and the subsequent internal attempt at a full handshake are unsuccessful.
|
||||
- The :cpp:type:`esp_tls_client_session_t` context should be freed using :cpp:func:`esp_tls_free_client_session` when it is no longer needed, or before a new session is obtained and stored in the same pointer.
|
||||
- For TLS 1.3, be mindful that the server can send multiple NewSessionTicket messages during a connection. Each successful call to :cpp:func:`esp_tls_get_client_session` will provide the context of the latest ticket processed by the underlying TLS stack. It is the application's responsibility to manage and update its stored session if it wishes to use the newest tickets for resumption.
|
||||
|
||||
TLS Ciphersuites
|
||||
----------------
|
||||
|
||||
ESP-TLS provides the ability to set a ciphersuites list in client mode. The TLS ciphersuites list informs the server about the supported ciphersuites for the specific TLS connection regardless of the TLS stack configuration. If the server supports any ciphersuite from this list, then the TLS connection will succeed; otherwise, it will 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.
|
||||
|
||||
TLS Protocol Version
|
||||
--------------------
|
||||
|
||||
ESP-TLS provides the ability to set the TLS protocol version for the respective TLS connection. Once the version is specified, it should be exclusively used to establish the TLS connection. This provides an ability to route different TLS connections to different protocol versions like TLS 1.2 and TLS 1.3 at runtime.
|
||||
|
||||
.. note::
|
||||
|
||||
At the moment, the feature is supported only when ESP-TLS is used with MbedTLS as its underlying SSL/TLS stack.
|
||||
|
||||
To set TLS protocol version with ESP-TLS, set :cpp:member:`esp_tls_cfg_t::tls_version` to the required protocol version from :cpp:type:`esp_tls_proto_ver_t`. If the protocol version field is not set, then the default policy is to allow TLS connection based on the server requirement.
|
||||
|
||||
The ESP-TLS connection can be configured to use the specified protocol version as follows:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include "esp_tls.h"
|
||||
esp_tls_cfg_t cfg = {
|
||||
.tls_version = ESP_TLS_VER_TLS_1_2,
|
||||
};
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
.. include-build-file:: inc/esp_tls.inc
|
||||
.. include-build-file:: inc/esp_tls_errors.inc
|
||||
.. include-build-file:: inc/esp_tls_custom_stack.inc
|
||||
@@ -0,0 +1,122 @@
|
||||
ICMP Echo
|
||||
=========
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
ICMP (Internet Control Message Protocol) is used for diagnostic or control purposes or generated in response to errors in IP operations. The common network util ``ping`` is implemented based on the ICMP packets with the type field value of 0, also called ``Echo Reply``.
|
||||
|
||||
During a ping session, the source host firstly sends out an ICMP echo request packet and wait for an ICMP echo reply with specific times. In this way, it also measures the round-trip time for the messages. After receiving a valid ICMP echo reply, the source host will generate statistics about the IP link layer (e.g., packet loss, elapsed time, etc).
|
||||
|
||||
It is common that IoT device needs to check whether a remote server is alive or not. The device should show the warnings to users when it got offline. It can be achieved by creating a ping session and sending or parsing ICMP echo packets periodically.
|
||||
|
||||
To make this internal procedure much easier for users, ESP-IDF provides some out-of-box APIs.
|
||||
|
||||
Create a New Ping Session
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To create a ping session, you need to fill in the ``esp_ping_config_t`` configuration structure firstly, specifying target IP address, interval times, and etc. Optionally, you can also register some callback functions with the ``esp_ping_callbacks_t`` structure.
|
||||
|
||||
Example method to create a new ping session and register callbacks:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
static void test_on_ping_success(esp_ping_handle_t hdl, void *args)
|
||||
{
|
||||
// optionally, get callback arguments
|
||||
// const char* str = (const char*) args;
|
||||
// printf("%s\r\n", str); // "foo"
|
||||
uint8_t ttl;
|
||||
uint16_t seqno;
|
||||
uint32_t elapsed_time, recv_len;
|
||||
ip_addr_t target_addr;
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_TTL, &ttl, sizeof(ttl));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_SIZE, &recv_len, sizeof(recv_len));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &elapsed_time, sizeof(elapsed_time));
|
||||
printf("%d bytes from %s icmp_seq=%d ttl=%d time=%d ms\n",
|
||||
recv_len, inet_ntoa(target_addr.u_addr.ip4), seqno, ttl, elapsed_time);
|
||||
}
|
||||
|
||||
static void test_on_ping_timeout(esp_ping_handle_t hdl, void *args)
|
||||
{
|
||||
uint16_t seqno;
|
||||
ip_addr_t target_addr;
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
|
||||
printf("From %s icmp_seq=%d timeout\n", inet_ntoa(target_addr.u_addr.ip4), seqno);
|
||||
}
|
||||
|
||||
static void test_on_ping_end(esp_ping_handle_t hdl, void *args)
|
||||
{
|
||||
uint32_t transmitted;
|
||||
uint32_t received;
|
||||
uint32_t total_time_ms;
|
||||
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_REQUEST, &transmitted, sizeof(transmitted));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_REPLY, &received, sizeof(received));
|
||||
esp_ping_get_profile(hdl, ESP_PING_PROF_DURATION, &total_time_ms, sizeof(total_time_ms));
|
||||
printf("%d packets transmitted, %d received, time %dms\n", transmitted, received, total_time_ms);
|
||||
}
|
||||
|
||||
void initialize_ping()
|
||||
{
|
||||
/* convert URL to IP address */
|
||||
ip_addr_t target_addr;
|
||||
struct addrinfo hint;
|
||||
struct addrinfo *res = NULL;
|
||||
memset(&hint, 0, sizeof(hint));
|
||||
memset(&target_addr, 0, sizeof(target_addr));
|
||||
getaddrinfo("www.espressif.com", NULL, &hint, &res);
|
||||
struct in_addr addr4 = ((struct sockaddr_in *) (res->ai_addr))->sin_addr;
|
||||
inet_addr_to_ip4addr(ip_2_ip4(&target_addr), &addr4);
|
||||
freeaddrinfo(res);
|
||||
|
||||
esp_ping_config_t ping_config = ESP_PING_DEFAULT_CONFIG();
|
||||
ping_config.target_addr = target_addr; // target IP address
|
||||
ping_config.count = ESP_PING_COUNT_INFINITE; // ping in infinite mode, esp_ping_stop can stop it
|
||||
|
||||
/* set callback functions */
|
||||
esp_ping_callbacks_t cbs;
|
||||
cbs.on_ping_success = test_on_ping_success;
|
||||
cbs.on_ping_timeout = test_on_ping_timeout;
|
||||
cbs.on_ping_end = test_on_ping_end;
|
||||
cbs.cb_args = "foo"; // arguments that feeds to all callback functions, can be NULL
|
||||
cbs.cb_args = eth_event_group;
|
||||
|
||||
esp_ping_handle_t ping;
|
||||
esp_ping_new_session(&ping_config, &cbs, &ping);
|
||||
}
|
||||
|
||||
Start and Stop Ping Session
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
You can start and stop ping session with the handle returned by ``esp_ping_new_session``. Note that, the ping session does not start automatically after creation. If the ping session is stopped, and restart again, the sequence number in ICMP packets will recount from zero again.
|
||||
|
||||
|
||||
Delete a Ping Session
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If a ping session will not be used any more, you can delete it with ``esp_ping_delete_session``. Please make sure the ping session is in stop state (i.e., you have called ``esp_ping_stop`` before or the ping session has finished all the procedures) when you call this function.
|
||||
|
||||
|
||||
Get Runtime Statistics
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
As the example code above, you can call ``esp_ping_get_profile`` to get different runtime statistics of ping session in the callback function.
|
||||
|
||||
|
||||
Application Examples
|
||||
--------------------
|
||||
|
||||
- :example:`protocols/icmp_echo` demonstrates how to implement a simple ping command line utility to test if a remote host is reachable on the IP network, using ICMP echo request packets.
|
||||
|
||||
- :example:`protocols/icmp/pmtu_probe` demonstrates how to probe path MTU with ICMP echo requests and apply the result to the active interface using :cpp:func:`esp_netif_set_mtu`.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
.. include-build-file:: inc/ping_sock.inc
|
||||
@@ -0,0 +1,28 @@
|
||||
Application Protocols
|
||||
*********************
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
asio
|
||||
modbus
|
||||
mqtt
|
||||
esp_tls
|
||||
esp_http_client
|
||||
esp_local_ctrl
|
||||
esp_crt_bundle
|
||||
esp_http_server
|
||||
esp_https_server
|
||||
icmp_echo
|
||||
mdns
|
||||
mbedtls
|
||||
|
||||
Code examples for this API section are provided in the :example:`protocols` directory of ESP-IDF examples.
|
||||
|
||||
|
||||
IP Network Layer
|
||||
================
|
||||
|
||||
Documentation for IP Network Layer protocols (below the Application Protocol layer) are provided in :doc:`../network/index`.
|
||||
@@ -0,0 +1,421 @@
|
||||
Mbed TLS
|
||||
========
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
`Mbed TLS <https://github.com/Mbed-TLS/mbedtls>`_ is a C library that implements cryptographic primitives, X.509 certificate manipulation and the SSL/TLS and DTLS protocols. Its small code footprint makes it suitable for embedded systems.
|
||||
|
||||
.. note::
|
||||
|
||||
ESP-IDF uses a `fork <https://github.com/espressif/mbedtls>`_ of Mbed TLS which includes a few patches (related to hardware routines of certain modules like ``bignum (MPI)`` and ``ECC``) over vanilla Mbed TLS.
|
||||
|
||||
Mbed TLS supports TLS 1.2, TLS 1.3 and DTLS 1.2 communication by providing the following:
|
||||
|
||||
- TCP/IP communication functions: listen, connect, accept, read/write.
|
||||
- SSL/TLS communication functions: init, handshake, read/write.
|
||||
- X.509 functions: CRT, CRL and key handling
|
||||
- Random number generation
|
||||
- Hashing
|
||||
- Encryption/decryption
|
||||
|
||||
.. note::
|
||||
|
||||
Mbed TLS v3.x.x series supports only TLS 1.2 and TLS 1.3 protocols. Support for SSL 3.0, TLS 1.0/1.1 and DTLS 1.0 has been removed (deprecated). TLS 1.3 is fully supported starting Mbed TLS v3.6.0 release, before this release some features were still in experimental state. Please refer to :component_file:`Mbed TLS ChangeLog <mbedtls/mbedtls/ChangeLog>` for more details.
|
||||
|
||||
Mbed TLS Documentation
|
||||
----------------------
|
||||
|
||||
For Mbed TLS documentation please refer to the following (upstream) pointers:
|
||||
|
||||
- `API Reference`_
|
||||
- `Knowledge Base`_
|
||||
|
||||
Mbed TLS Support in ESP-IDF
|
||||
---------------------------
|
||||
|
||||
Please find the information about the Mbed TLS versions presented in different branches of ESP-IDF `here <https://github.com/espressif/mbedtls/wiki#mbed-tls-support-in-esp-idf>`__.
|
||||
|
||||
.. note::
|
||||
|
||||
Please refer the :ref:`migration_guide_mbedtls` to migrate from Mbed TLS version 2.x to version 3.0 or greater.
|
||||
|
||||
Configuration Presets
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
ESP-IDF provides a preset-based configuration system for Mbed TLS to simplify setup and provide optimized starting points for different use cases. This system works alongside the existing manual configuration system and provides baseline configurations that can be further customized through menuconfig or additional configuration files.
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:widths: 15 25 35
|
||||
:align: center
|
||||
|
||||
* - Preset
|
||||
- Use Case
|
||||
- Key Features
|
||||
* - **Default**
|
||||
- General purpose applications
|
||||
- • TLS 1.2 & 1.3 support
|
||||
• Certificate bundle enabled
|
||||
• Hardware acceleration
|
||||
• Full cipher suite support
|
||||
* - **Minimal**
|
||||
- Resource-constrained applications
|
||||
- • TLS 1.2 client only
|
||||
• RSA & PSK key exchange
|
||||
• AES-128 CBC/CTR modes
|
||||
• Basic X.509 parsing
|
||||
* - **Bluetooth (BT)**
|
||||
- Bluetooth applications
|
||||
- • Optimized for Bluetooth LE security
|
||||
• ECC P-256 curve support
|
||||
• Minimal TLS overhead
|
||||
• Bluetooth-specific algorithms
|
||||
|
||||
Using Configuration Presets
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Presets serve as **starting points** for your mbedTLS configuration. You can use them as-is or customize them further using standard ESP-IDF configuration methods.
|
||||
|
||||
To use a preset configuration, add the following line to your project's ``CMakeLists.txt`` file **before** the ``project()`` call:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
# Include the default preset (recommended for most applications)
|
||||
list(APPEND sdkconfig_defaults $ENV{IDF_PATH}/components/mbedtls/config/mbedtls_preset_default.conf)
|
||||
|
||||
# Or for resource-constrained applications
|
||||
list(APPEND sdkconfig_defaults $ENV{IDF_PATH}/components/mbedtls/config/mbedtls_preset_minimal.conf)
|
||||
|
||||
# Or for Bluetooth applications
|
||||
list(APPEND sdkconfig_defaults $ENV{IDF_PATH}/components/mbedtls/config/mbedtls_preset_bt.conf)
|
||||
|
||||
# Standard ESP-IDF project setup
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(my_project)
|
||||
|
||||
.. note::
|
||||
|
||||
The preset configurations are located in ``components/mbedtls/config/`` and can be customized or used as a starting point for your own configurations.
|
||||
|
||||
Customizing Preset Configurations
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
After applying a preset, you can further customize the configuration using any of these methods:
|
||||
|
||||
**Method 1: Using menuconfig (Recommended)**
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# After applying a preset in CMakeLists.txt
|
||||
idf.py menuconfig
|
||||
|
||||
Navigate to ``Component Config`` > ``mbedTLS`` to modify any settings. Your changes will override the preset defaults.
|
||||
|
||||
**Method 2: Additional Configuration Files**
|
||||
|
||||
You can combine a preset with your own custom configuration by creating an additional configuration file:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
# Use the minimal preset as a base, then add custom settings
|
||||
list(APPEND SDKCONFIG_DEFAULTS
|
||||
$ENV{IDF_PATH}/components/mbedtls/config/mbedtls_preset_minimal.conf
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/my_custom_mbedtls.conf
|
||||
)
|
||||
|
||||
|
||||
Migration from Manual Configuration
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The preset system complements manual configuration. If you have an existing manually configured mbedTLS setup:
|
||||
|
||||
**Option 1: Keep Your Existing Configuration**
|
||||
|
||||
Your current manual configuration will continue to work without any changes.
|
||||
|
||||
**Option 2: Migrate to Preset + Customization**
|
||||
|
||||
1. **Choose a base preset** that's closest to your current configuration.
|
||||
2. **Apply the preset** in your ``CMakeLists.txt``.
|
||||
3. **Use menuconfig** to adjust settings to match your requirements.
|
||||
4. **Test thoroughly** to ensure functionality is maintained.
|
||||
|
||||
Configuration Categories
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The new mbedTLS configuration system is organized into logical categories for easier navigation:
|
||||
|
||||
**Core Configuration**
|
||||
Basic mbedTLS settings including memory allocation, threading, and debug options.
|
||||
|
||||
**TLS Protocol Configuration**
|
||||
TLS/DTLS protocol versions, modes (client/server), and protocol-specific features.
|
||||
|
||||
**Symmetric Ciphers**
|
||||
Block ciphers (AES, ARIA, etc.), cipher modes (CBC, GCM, etc.), and symmetric cryptography.
|
||||
|
||||
**Asymmetric Ciphers**
|
||||
RSA, ECC, and other public key cryptography algorithms.
|
||||
|
||||
**Hash Functions**
|
||||
Message digest algorithms (SHA-256, SHA-512, etc.) and HMAC.
|
||||
|
||||
**Hardware Acceleration**
|
||||
ESP32-specific hardware acceleration for cryptographic operations.
|
||||
|
||||
**Certificate Support**
|
||||
X.509 certificate parsing, validation, and certificate bundle management.
|
||||
|
||||
|
||||
PSA ITS Custom Storage Backend
|
||||
-------------------------------
|
||||
|
||||
ESP-IDF's PSA Internal Trusted Storage (ITS) implementation uses NVS as its default backend for storing persistent PSA Crypto keys. The custom storage backend feature allows routing a reserved range of PSA key IDs to a user-provided storage implementation, while all other keys continue using NVS.
|
||||
|
||||
This is useful when:
|
||||
|
||||
- Certain keys need to be stored on a different filesystem (FATFS, SPIFFS, littlefs)
|
||||
- Keys require hardware-protected encryption (e.g., via TEE secure storage)
|
||||
- Different storage partitions are needed for different key categories
|
||||
|
||||
Enabling the Custom Backend
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Enable the feature via ``menuconfig`` under ``Component Config`` > ``mbedTLS``:
|
||||
|
||||
- :ref:`CONFIG_MBEDTLS_PSA_ITS_CUSTOM_STORAGE_BACKEND`: Enable the custom storage backend
|
||||
- :ref:`CONFIG_MBEDTLS_PSA_ITS_CUSTOM_BACKEND_UID_MIN`: Start of the custom key ID range (default ``0x30000000``)
|
||||
- :ref:`CONFIG_MBEDTLS_PSA_ITS_CUSTOM_BACKEND_UID_MAX`: End of the custom key ID range (default ``0x3FFFFFFF``)
|
||||
|
||||
PSA key IDs within the configured range are routed to the registered backend. All other key IDs (and internal PSA data such as the random seed) continue using the default NVS backend.
|
||||
|
||||
Implementing a Custom Backend
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Implement the ``esp_psa_its_custom_ops_t`` callback structure and register it before using PSA Crypto with keys in the custom range:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include "esp_psa_its.h"
|
||||
|
||||
static psa_status_t my_set(void *ctx, const psa_storage_uid_t uid,
|
||||
const uint32_t data_length, const void *p_data,
|
||||
const psa_storage_create_flags_t create_flags)
|
||||
{
|
||||
/* Store the blob identified by uid */
|
||||
}
|
||||
|
||||
static psa_status_t my_get(void *ctx, const psa_storage_uid_t uid,
|
||||
const uint32_t data_offset, const uint32_t data_length,
|
||||
void *p_data, size_t *p_data_length)
|
||||
{
|
||||
/* Retrieve the blob identified by uid */
|
||||
}
|
||||
|
||||
static psa_status_t my_get_info(void *ctx, const psa_storage_uid_t uid,
|
||||
struct psa_storage_info_t *p_info)
|
||||
{
|
||||
/* Return size and flags for the blob identified by uid */
|
||||
}
|
||||
|
||||
static psa_status_t my_remove(void *ctx, const psa_storage_uid_t uid)
|
||||
{
|
||||
/* Delete the blob identified by uid */
|
||||
}
|
||||
|
||||
static esp_psa_its_custom_ops_t my_ops = {
|
||||
.set = my_set,
|
||||
.get = my_get,
|
||||
.get_info = my_get_info,
|
||||
.remove = my_remove,
|
||||
.ctx = NULL, /* optional user context */
|
||||
};
|
||||
|
||||
/* Register before using PSA keys in the custom range */
|
||||
esp_psa_its_register_custom_backend(&my_ops);
|
||||
|
||||
The callback signatures mirror the PSA ITS API. Each callback receives the raw ``psa_storage_uid_t`` (not a string), allowing the implementation to make routing decisions based on the numeric key ID. The ``ctx`` pointer is passed as the first argument to every callback.
|
||||
|
||||
.. note::
|
||||
|
||||
Only persistent keys flow through the ITS layer. PSA requires ``psa_set_key_id()`` for persistent keys, so the application always controls which key IDs it assigns and thus which range they fall into.
|
||||
|
||||
The backend implementation is responsible for enforcing ``psa_storage_create_flags_t`` semantics if needed.
|
||||
|
||||
Working with the PSA Key Blob Format
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The byte stream that flows through ``psa_its_set()`` / ``psa_its_get()`` is the PSA persistent key blob format documented in the Mbed TLS `storage specification <https://github.com/Mbed-TLS/TF-PSA-Crypto/blob/development/docs/architecture/mbed-crypto-storage-specification.md>`__. Backends that store the blob verbatim do not need to look inside it. Backends that strip the header on write (to save space) or synthesise the blob on read (for example, to expose a pre-provisioned hardware key) need to construct or parse it themselves.
|
||||
|
||||
ESP-IDF provides two helpers in ``esp_psa_key_file.h`` for this:
|
||||
|
||||
- :cpp:func:`esp_psa_key_file_pack` — assemble a key blob from a ``psa_key_attributes_t`` structure and raw key material bytes.
|
||||
- :cpp:func:`esp_psa_key_file_unpack` — parse a key blob back into attributes and a pointer into the key material section.
|
||||
- :cpp:func:`esp_psa_key_file_size` — return the total blob size for a given material length.
|
||||
|
||||
These helpers implement the documented byte layout directly and do not depend on any internal Mbed TLS function. For example, a backend that stores only the inner key bytes can rebuild the blob on read:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include "esp_psa_key_file.h"
|
||||
|
||||
psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
|
||||
psa_set_key_lifetime(&attr, PSA_KEY_LIFETIME_PERSISTENT);
|
||||
psa_set_key_type(&attr, PSA_KEY_TYPE_AES);
|
||||
psa_set_key_bits(&attr, key_data_len * 8);
|
||||
psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
|
||||
psa_set_key_algorithm(&attr, PSA_ALG_CBC_NO_PADDING);
|
||||
|
||||
size_t blob_size = esp_psa_key_file_size(key_data_len);
|
||||
uint8_t *blob = calloc(1, blob_size);
|
||||
size_t written = 0;
|
||||
esp_psa_key_file_pack(&attr, key_data, key_data_len, blob, blob_size, &written);
|
||||
/* blob now holds the full PSA persistent key file; copy the requested
|
||||
* window into p_data per psa_its_get()'s offset/length arguments. */
|
||||
|
||||
For a complete working example using a custom NVS namespace as the custom backend, refer to :example:`security/psa_its_custom_backend`.
|
||||
|
||||
Application Examples
|
||||
--------------------
|
||||
|
||||
Examples in ESP-IDF use :doc:`/api-reference/protocols/esp_tls` which provides a simplified API interface for accessing the commonly used TLS functionality.
|
||||
|
||||
Refer to the examples :example:`protocols/https_server/simple` (simple HTTPS server) and :example:`protocols/https_request` (make HTTPS requests) for more information.
|
||||
|
||||
If you plan to use the Mbed TLS API directly, refer to the example :example:`protocols/https_mbedtls`. This example demonstrates how to establish an HTTPS connection using Mbed TLS by setting up a secure socket with a certificate bundle for verification.
|
||||
|
||||
The example :example:`protocols/smtp_client` sends email (including attachments) over SMTP with STARTTLS using the Mbed TLS APIs.
|
||||
|
||||
|
||||
Important Config Options
|
||||
------------------------
|
||||
|
||||
The Mbed TLS configuration system supports preset configurations. Following is a brief list of important config options accessible at ``Component Config`` > ``mbedTLS``. The full list of config options can be found :ref:`here <CONFIG_MBEDTLS_MEM_ALLOC_MODE>`.
|
||||
|
||||
**Core Configuration:**
|
||||
|
||||
.. list::
|
||||
|
||||
:SOC_SHA_SUPPORTED: - :ref:`CONFIG_MBEDTLS_HARDWARE_SHA`: Support for hardware SHA acceleration
|
||||
:SOC_AES_SUPPORTED: - :ref:`CONFIG_MBEDTLS_HARDWARE_AES`: Support for hardware AES acceleration
|
||||
:SOC_MPI_SUPPORTED: - :ref:`CONFIG_MBEDTLS_HARDWARE_MPI`: Support for hardware MPI (bignum) acceleration
|
||||
:SOC_ECC_SUPPORTED: - :ref:`CONFIG_MBEDTLS_HARDWARE_ECC`: Support for hardware ECC acceleration
|
||||
- :ref:`CONFIG_MBEDTLS_MEM_ALLOC_MODE`: Memory allocation strategy (Internal/External/Custom)
|
||||
- :ref:`CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN`: Asymmetric in/out fragment length for memory optimization
|
||||
- :ref:`CONFIG_MBEDTLS_DYNAMIC_BUFFER`: Enable dynamic TX/RX buffer allocation
|
||||
- :ref:`CONFIG_MBEDTLS_DEBUG`: Enable mbedTLS debugging (useful for debugging)
|
||||
|
||||
**TLS Protocol Configuration:**
|
||||
|
||||
.. list::
|
||||
|
||||
- :ref:`CONFIG_MBEDTLS_TLS_ENABLED`: Enable TLS protocol support
|
||||
- :ref:`CONFIG_MBEDTLS_SSL_PROTO_TLS1_2`: Support for TLS 1.2 (recommended)
|
||||
- :ref:`CONFIG_MBEDTLS_SSL_PROTO_TLS1_3`: Support for TLS 1.3 (latest standard)
|
||||
- :ref:`CONFIG_MBEDTLS_SSL_PROTO_DTLS`: Support for DTLS (UDP-based TLS)
|
||||
- :ref:`CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS`: Support for TLS Session Resumption (client session tickets)
|
||||
- :ref:`CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS`: Support for TLS Session Resumption Server session tickets
|
||||
- :ref:`CONFIG_MBEDTLS_SSL_ALPN`: Support for Application Layer Protocol Negotiation
|
||||
- :ref:`CONFIG_MBEDTLS_SSL_SERVER_NAME_INDICATION`: Support for Server Name Indication (SNI)
|
||||
|
||||
**Certificate Support:**
|
||||
|
||||
.. list::
|
||||
|
||||
- :ref:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE`: Support for trusted root certificate bundle (more about this: :doc:`/api-reference/protocols/esp_crt_bundle`)
|
||||
- :ref:`CONFIG_MBEDTLS_X509_USE_C`: Enable X.509 certificate support
|
||||
- :ref:`CONFIG_MBEDTLS_PEM_PARSE_C`: Read & Parse PEM formatted certificates
|
||||
- :ref:`CONFIG_MBEDTLS_PEM_WRITE_C`: Write PEM formatted certificates
|
||||
- :ref:`CONFIG_MBEDTLS_X509_CRT_PARSE_C`: Parse X.509 certificates
|
||||
- :ref:`CONFIG_MBEDTLS_X509_CRL_PARSE_C`: Parse X.509 certificate revocation lists
|
||||
|
||||
**Cryptographic Algorithms:**
|
||||
|
||||
.. list::
|
||||
|
||||
- :ref:`CONFIG_MBEDTLS_AES_C`: AES block cipher support
|
||||
- :ref:`CONFIG_MBEDTLS_RSA_C`: RSA public key cryptosystem
|
||||
- :ref:`CONFIG_MBEDTLS_ECP_C`: Elliptic Curve Cryptography support
|
||||
- :ref:`CONFIG_MBEDTLS_ECDSA_C`: Elliptic Curve Digital Signature Algorithm
|
||||
- :ref:`CONFIG_MBEDTLS_ECDH_C`: Elliptic Curve Diffie-Hellman key exchange
|
||||
- :ref:`CONFIG_MBEDTLS_SHA256_C`: SHA-256 hash function
|
||||
- :ref:`CONFIG_MBEDTLS_SHA512_C`: SHA-512 hash function
|
||||
- :ref:`CONFIG_MBEDTLS_GCM_C`: Galois/Counter Mode for authenticated encryption
|
||||
|
||||
.. note::
|
||||
|
||||
The new configuration structure provides better organization with categories like "Core Configuration", "TLS Protocol Configuration", "Symmetric Ciphers", "Asymmetric Ciphers", "Hash Functions", and "Hardware Acceleration" for easier navigation and configuration management.
|
||||
|
||||
Debugging mbedTLS
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
To enable debugging, add these configurations:
|
||||
|
||||
.. code-block:: kconfig
|
||||
|
||||
CONFIG_MBEDTLS_DEBUG=y
|
||||
CONFIG_MBEDTLS_DEBUG_LEVEL=3
|
||||
CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y
|
||||
|
||||
Performance Optimization
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For optimal performance, **enable hardware acceleration** when available:
|
||||
|
||||
.. code-block:: kconfig
|
||||
|
||||
CONFIG_MBEDTLS_HARDWARE_AES=y
|
||||
CONFIG_MBEDTLS_HARDWARE_SHA=y
|
||||
CONFIG_MBEDTLS_HARDWARE_MPI=y
|
||||
CONFIG_MBEDTLS_HARDWARE_ECC=y
|
||||
|
||||
Performance and Memory Tweaks
|
||||
-----------------------------
|
||||
|
||||
.. _reducing_ram_usage_mbedtls:
|
||||
|
||||
Reducing Heap Usage
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The following table shows typical memory usage with different configs when the :example:`protocols/https_request` example (with Server Validation enabled) is run with Mbed TLS as the SSL/TLS library.
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:widths: 25 60 30
|
||||
:align: center
|
||||
|
||||
* - Mbed TLS Test
|
||||
- Related Configs
|
||||
- Heap Usage (approx.)
|
||||
* - Default
|
||||
- NA
|
||||
- 42196 B
|
||||
* - Enable SSL Dynamic Buffer Length
|
||||
- :ref:`CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH`
|
||||
- 42120 B
|
||||
* - Disable Keep Peer Certificate
|
||||
- :ref:`CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE`
|
||||
- 38533 B
|
||||
* - Enable Dynamic TX/RX Buffer
|
||||
- :ref:`CONFIG_MBEDTLS_DYNAMIC_BUFFER`
|
||||
:ref:`CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA`
|
||||
:ref:`CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT`
|
||||
- 22013 B
|
||||
|
||||
.. note::
|
||||
|
||||
These values are subject to change with changes in configuration options and versions of Mbed TLS.
|
||||
|
||||
.. note::
|
||||
|
||||
:ref:`CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_CROSS_SIGNED_VERIFY` is enabled by default. If cross-signed certificate chains are not required, disabling it reduces peak heap usage during the TLS handshake by approximately 1 KB, at the cost of a larger certificate bundle in flash. See :doc:`/api-reference/protocols/esp_crt_bundle` for details.
|
||||
|
||||
|
||||
Reducing Binary Size
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Under ``Component Config`` > ``mbedTLS``, several Mbed TLS features are enabled by default. These can be disabled if not needed to save code size. More information is available in the :ref:`Minimizing Binary Size <minimizing_binary_mbedtls>` documentation.
|
||||
|
||||
|
||||
.. _`API Reference`: https://mbed-tls.readthedocs.io/projects/api/en/v3.6.5/
|
||||
.. _`Knowledge Base`: https://mbed-tls.readthedocs.io/en/latest/kb/
|
||||
@@ -0,0 +1,19 @@
|
||||
mDNS Service
|
||||
============
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
mDNS is a multicast UDP service that is used to provide local network service and host discovery.
|
||||
|
||||
The ESP-IDF component ``mDNS`` has been moved from ESP-IDF since version v5.0 to a separate repository:
|
||||
|
||||
* `mDNS component on GitHub <https://github.com/espressif/esp-protocols/tree/master/components/mdns>`__
|
||||
|
||||
To add mDNS component in your project, please run ``idf.py add-dependency espressif/mdns``.
|
||||
|
||||
Hosted Documentation
|
||||
--------------------
|
||||
|
||||
The documentation can be found on the link below:
|
||||
|
||||
* `mDNS documentation <https://docs.espressif.com/projects/esp-protocols/mdns/docs/latest/en/index.html>`__
|
||||
@@ -0,0 +1,27 @@
|
||||
ESP-Modbus
|
||||
==========
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
The Espressif ESP-Modbus Library (esp-modbus) supports Modbus communication in the networks based on RS485, Wi-Fi, and Ethernet interfaces.
|
||||
The component ``esp-modbus v2 (v2.x.x)`` is the current supported component version:
|
||||
|
||||
* `ESP-Modbus component on GitHub <https://github.com/espressif/esp-modbus/tree/main>`__
|
||||
* `ESP-Modbus component in component manager <https://components.espressif.com/components/espressif/esp-modbus>`__
|
||||
|
||||
Hosted Documentation
|
||||
--------------------
|
||||
|
||||
The documentation can be found through the link below:
|
||||
|
||||
* `ESP-Modbus V2 documentation (English) <https://docs.espressif.com/projects/esp-modbus/en/stable>`__
|
||||
|
||||
Discussions
|
||||
~~~~~~~~~~~
|
||||
|
||||
* `Discussions for version v2 <https://github.com/espressif/esp-modbus/discussions>`__
|
||||
|
||||
Protocol References
|
||||
-------------------
|
||||
|
||||
- For the detailed protocol specifications, see `The Modbus Organization <https://modbus.org/specs.php>`_.
|
||||
@@ -0,0 +1,40 @@
|
||||
ESP-MQTT
|
||||
========
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
ESP-MQTT is an implementation of `MQTT <https://mqtt.org/>`__ protocol client, which is a lightweight publish/subscribe messaging protocol. Now ESP-MQTT supports `MQTT v5.0 <https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html>`__.
|
||||
|
||||
The ESP-IDF component ``ESP-MQTT`` has been moved from ESP-IDF since version v6.0 to a separate repository:
|
||||
|
||||
* `esp-mqtt component on GitHub <https://github.com/espressif/esp-mqtt>`__
|
||||
|
||||
To add ESP-MQTT component in your project, please run ``idf.py add-dependency espressif/mqtt``.
|
||||
|
||||
Hosted Documentation
|
||||
---------------------
|
||||
|
||||
The documentation can be found on the link below:
|
||||
|
||||
* `esp-mqtt documentation <https://docs.espressif.com/projects/esp-mqtt/en/latest/>`__
|
||||
|
||||
Application Examples
|
||||
--------------------
|
||||
|
||||
Two reference examples are available in ESP-IDF:
|
||||
|
||||
- MQTT over TLS (certificate bundle): :example:`protocols/mqtt`
|
||||
|
||||
- Validates the broker with ESP-IDF's certificate bundle (default).
|
||||
- Default broker URI targets ``mqtts://test.mosquitto.org:8886`` (Let's Encrypt chain).
|
||||
- Alternative configuration pins Mosquitto CA and uses ``mqtts://test.mosquitto.org:8883``.
|
||||
|
||||
- MQTT 5.0 over TLS (certificate bundle): :example:`protocols/mqtt5`
|
||||
|
||||
- Uses MQTT v5.0 with TLS and validation via the certificate bundle.
|
||||
- Default broker URI targets ``mqtts://test.mosquitto.org:8886``.
|
||||
|
||||
For additional transport modes (TCP, WS/WSS, mutual auth, etc.), see the examples in the `espressif/mqtt component repository <https://components.espressif.com/components/espressif/mqtt>`__.
|
||||
Reference in New Issue
Block a user