From 489ee924f053e0001c3feb1edc3ad04b3f6b225d Mon Sep 17 00:00:00 2001 From: "hrushikesh.bhosale" Date: Tue, 14 Jul 2026 14:54:06 +0530 Subject: [PATCH 1/4] feat(esp-wolfssl): support esp_key_config_t key in esp-tls server and client paths esp_https_server / esp_tls (and their examples) pass the private key via the unified esp_key_config_t (cfg->server_key / cfg->client_key) instead of the legacy serverkey_buf / clientkey_buf on newer ESP-IDF. Accept the unified key config (ESP_KEY_SOURCE_BUFFER) as a fallback on both the server and client paths. The interface was added to esp-tls after v6.0, so it is detected via __has_include("esp_key_config.h") to keep building on v6.0 and earlier (which only have the *_buf fields). --- port/esp_tls_wolfssl.c | 50 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/port/esp_tls_wolfssl.c b/port/esp_tls_wolfssl.c index ed8127b..961d65c 100644 --- a/port/esp_tls_wolfssl.c +++ b/port/esp_tls_wolfssl.c @@ -318,19 +318,36 @@ static esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls #endif } - if (cfg->clientcert_buf != NULL && cfg->clientkey_buf != NULL) { + /* Resolve the client private key the same way as the server key above: + * prefer the legacy clientkey_buf, but also accept the unified key config + * (cfg->client_key), detected via __has_include (see the server path). */ + const unsigned char *clientkey_buf = cfg->clientkey_buf; + unsigned int clientkey_bytes = cfg->clientkey_bytes; +#if defined(__has_include) && __has_include("esp_key_config.h") + if (clientkey_buf == NULL && cfg->client_key != NULL) { + if (cfg->client_key->source == ESP_KEY_SOURCE_BUFFER) { + clientkey_buf = (const unsigned char *)cfg->client_key->buffer.data; + clientkey_bytes = (unsigned int)cfg->client_key->buffer.len; + } else { + ESP_LOGE(TAG, "Unsupported client_key source %d for wolfSSL backend (only ESP_KEY_SOURCE_BUFFER)", cfg->client_key->source); + return ESP_FAIL; + } + } +#endif /* __has_include("esp_key_config.h") */ + + if (cfg->clientcert_buf != NULL && clientkey_buf != NULL) { if ((esp_load_wolfssl_verify_buffer(tls,cfg->clientcert_buf, cfg->clientcert_bytes, FILE_TYPE_SELF_CERT, &ret)) != ESP_OK) { ESP_LOGE(TAG, "Error in loading certificate verify buffer, returned %d", ret); wolfssl_print_error_msg(ret); return ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED; } - if ((esp_load_wolfssl_verify_buffer(tls,cfg->clientkey_buf, cfg->clientkey_bytes, FILE_TYPE_SELF_KEY, &ret)) != ESP_OK) { + if ((esp_load_wolfssl_verify_buffer(tls,clientkey_buf, clientkey_bytes, FILE_TYPE_SELF_KEY, &ret)) != ESP_OK) { ESP_LOGE(TAG, "Error in loading private key verify buffer, returned %d", ret); wolfssl_print_error_msg(ret); return ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED; } - } else if (cfg->clientcert_buf != NULL || cfg->clientkey_buf != NULL) { - ESP_LOGE(TAG, "You have to provide both clientcert_buf and clientkey_buf for mutual authentication"); + } else if (cfg->clientcert_buf != NULL || clientkey_buf != NULL) { + ESP_LOGE(TAG, "You have to provide both clientcert_buf and a client key (clientkey_buf or client_key) for mutual authentication"); return ESP_FAIL; } @@ -431,19 +448,38 @@ static esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls) wolfSSL_CTX_set_verify( (WOLFSSL_CTX *)tls->priv_ctx, WOLFSSL_VERIFY_NONE, NULL); } - if (cfg->servercert_buf != NULL && cfg->serverkey_buf != NULL) { + /* Accept the unified key config (cfg->server_key) as well as the legacy + * serverkey_buf. Only the in-memory BUFFER source is supported. The unified + * esp_key_config_t interface was added to esp-tls after v6.0, so detect it + * by header presence (it is absent on v6.0 and earlier, which only have + * serverkey_buf) rather than by IDF version number. */ + const unsigned char *serverkey_buf = cfg->serverkey_buf; + unsigned int serverkey_bytes = cfg->serverkey_bytes; +#if defined(__has_include) && __has_include("esp_key_config.h") + if (serverkey_buf == NULL && cfg->server_key != NULL) { + if (cfg->server_key->source == ESP_KEY_SOURCE_BUFFER) { + serverkey_buf = (const unsigned char *)cfg->server_key->buffer.data; + serverkey_bytes = (unsigned int)cfg->server_key->buffer.len; + } else { + ESP_LOGE(TAG, "Unsupported server_key source %d for wolfSSL backend (only ESP_KEY_SOURCE_BUFFER)", cfg->server_key->source); + return ESP_FAIL; + } + } +#endif /* __has_include("esp_key_config.h") */ + + if (cfg->servercert_buf != NULL && serverkey_buf != NULL) { if ((esp_load_wolfssl_verify_buffer(tls,cfg->servercert_buf, cfg->servercert_bytes, FILE_TYPE_SELF_CERT, &ret)) != ESP_OK) { ESP_LOGE(TAG, "Error in loading certificate verify buffer, returned %d", ret); wolfssl_print_error_msg(ret); return ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED; } - if ((esp_load_wolfssl_verify_buffer(tls,cfg->serverkey_buf, cfg->serverkey_bytes, FILE_TYPE_SELF_KEY, &ret)) != ESP_OK) { + if ((esp_load_wolfssl_verify_buffer(tls,serverkey_buf, serverkey_bytes, FILE_TYPE_SELF_KEY, &ret)) != ESP_OK) { ESP_LOGE(TAG, "Error in loading private key verify buffer, returned %d", ret); wolfssl_print_error_msg(ret); return ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED; } } else { - ESP_LOGE(TAG, "You have to provide both servercert_buf and serverkey_buf for https_server"); + ESP_LOGE(TAG, "You have to provide a server certificate (servercert_buf) and key (serverkey_buf or server_key) for https_server"); return ESP_FAIL; } From 9799c774692670b368ea8fd2d339fd80c5b6b52d Mon Sep 17 00:00:00 2001 From: "hrushikesh.bhosale" Date: Tue, 14 Jul 2026 14:54:06 +0530 Subject: [PATCH 2/4] fix(esp-wolfssl): don't build esp_tls_wolfssl.c on ESP-IDF < 6.0 port/esp_tls_wolfssl.c includes esp_tls_custom_stack.h, which only exists in ESP-IDF v6.0+. Exclude it from the sources when CONFIG_ESP_TLS_CUSTOM_STACK is unset, so the component still builds on v5.5 and earlier (native wolfSSL API). --- CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 91ec379..6d91d3c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,14 @@ set(COMPONENT_SRCEXCLUDE_1 "wolfssl/wolfcrypt/src/ext_xmss.c" ) +# port/esp_tls_wolfssl.c integrates wolfSSL as an esp-tls "custom stack", which +# relies on esp_tls_custom_stack.h -- a header that only exists in ESP-IDF >= 6.0. +# On older IDF that header is absent, so exclude the file there; the component +# still builds and is usable via the native wolfSSL API (see examples/wolfssl_client). +if(NOT CONFIG_ESP_TLS_CUSTOM_STACK) + list(APPEND COMPONENT_SRCEXCLUDE_1 "port/esp_tls_wolfssl.c") +endif() + idf_component_register(SRC_DIRS "${COMPONENT_SRCDIRS}" INCLUDE_DIRS "${COMPONENT_ADD_INCLUDEDIRS}" REQUIRES "${COMPONENT_REQUIRES}" From d5b63e96b7b27dd1966eb4e90eb520bae65983b6 Mon Sep 17 00:00:00 2001 From: "hrushikesh.bhosale" Date: Tue, 14 Jul 2026 14:54:06 +0530 Subject: [PATCH 3/4] feat(esp-wolfssl): define ESP_TLS_HAS_WOLFSSL macro Lets application code feature-detect the wolfSSL backend with #ifdef ESP_TLS_HAS_WOLFSSL, mirroring the macro ESP-IDF defined when wolfSSL was a built-in esp-tls backend. Migrated from esp-idf#17682 (supersedes PR #29). --- include/esp_wolfssl_stack.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/esp_wolfssl_stack.h b/include/esp_wolfssl_stack.h index ad18ed0..a58ccfe 100644 --- a/include/esp_wolfssl_stack.h +++ b/include/esp_wolfssl_stack.h @@ -15,6 +15,21 @@ extern "C" { #if CONFIG_ESP_TLS_CUSTOM_STACK +/** + * @brief Indicates that the wolfSSL TLS backend is available in this build. + * + * Defined whenever this component is part of the build with the ESP-TLS custom + * stack enabled (wolfSSL registers itself as that stack). Application code can + * `#ifdef ESP_TLS_HAS_WOLFSSL` to feature-detect wolfSSL. + * + * This mirrors the ESP_TLS_HAS_WOLFSSL macro that ESP-IDF used to define in + * esp_tls.h when wolfSSL was a built-in esp-tls backend + * (CONFIG_ESP_TLS_USING_WOLFSSL). It is kept under the same name so code that + * already feature-detects wolfSSL this way keeps working now that wolfSSL + * lives in the esp-wolfssl component. + */ +#define ESP_TLS_HAS_WOLFSSL + /** * @brief Register wolfSSL as the custom TLS stack for ESP-TLS * From 8fe8b0c06b73d79711414fc9b35efecb9b3484c9 Mon Sep 17 00:00:00 2001 From: "hrushikesh.bhosale" Date: Tue, 14 Jul 2026 14:54:06 +0530 Subject: [PATCH 4/4] docs(esp-wolfssl): document path-based usage; drop registry instructions The component is consumed by cloning it and adding a path-based dependency; remove the IDF Component Registry / add-dependency instructions. --- README.md | 280 +++++++++++++++++++++++++----------------------------- 1 file changed, 128 insertions(+), 152 deletions(-) diff --git a/README.md b/README.md index b510027..3361624 100644 --- a/README.md +++ b/README.md @@ -1,152 +1,128 @@ -ESP-WOLFSSL -=========== - -# Licensing - - ---- -**IMPORTANT NOTE** - -Until March 2021, this repository contained binary distribution of wolfSSL libraries, which could be used royalty-free on all Espressif MCU products. This royalty-free binary distribution is not available anymore. - -This repository now uses upstream wolfSSL GitHub pointer as submodule and can still be used as ESP-IDF component. Please follow licensing requirements per [wolfssl/LICENSING](https://github.com/wolfSSL/wolfssl/blob/master/LICENSING) - ---- - -# Requirements -- ESP_IDF - - To use `esp-wolfssl` as the esp-tls custom TLS stack (recommended, see below), ESP-IDF v6.x or later (master) is required — `CONFIG_ESP_TLS_CUSTOM_STACK` is not available in earlier releases. - - To use the wolfSSL native APIs directly (as in `examples/wolfssl_client`), ESP-IDF v4.1 or later is sufficient. - - The IDF_PATH should be set as an environment variable - -# Getting Started - -- Please clone this repository using, - ``` - git clone --recursive https://github.com/espressif/esp-wolfssl - ``` -- Please refer to https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html for setting ESP-IDF - - ESP-IDF can be downloaded from https://github.com/espressif/esp-idf/ - - ESP-IDF v4.1 and above is recommended version -- Please refer to [example README](examples/README.md) for more information on setting up examples - -# Using esp-wolfssl as a custom esp-tls stack (ESP-IDF 6.x) - -From ESP-IDF 6.x onwards, `esp-tls` supports pluggable TLS backends via -`CONFIG_ESP_TLS_CUSTOM_STACK`. `esp-wolfssl` registers itself automatically -with `esp-tls` during system init (via `ESP_SYSTEM_INIT_FN`), so applications -that already use the `esp_tls_*` APIs (or any higher-level component built on -top — `esp_http_client`, `esp_https_ota`, `esp_https_server`, `esp-mqtt`, etc.) -work unchanged. **No code changes are needed in `app_main`; you do not need to -call `esp_wolfssl_register_stack()` explicitly.** - -The only requirement is that the `esp-wolfssl` component must be part of your -build so that the auto-registration init function gets linked in. The -recommended way to do that is via the IDF Component Manager: - -```bash -# From the root of your project (the directory that contains main/): -idf.py add-dependency "espressif/esp-wolfssl^1.0.0" -``` - -> Note: until this version of the component is published to the -> [IDF Component Registry](https://components.espressif.com), use the -> path-based dependency described below instead. - -This creates (or updates) `main/idf_component.yml` with an entry like: - -```yaml -dependencies: - espressif/esp-wolfssl: "^1.0.0" -``` - -The Component Manager then injects `esp-wolfssl` into `main`'s private -requirements before the build's dependency tree is expanded, so the component -is pulled in even under `MINIMAL_BUILD` projects without any further wiring. - -Finally, enable the custom stack and (re)build: - -```bash -idf.py menuconfig -# → Component config -# → ESP-TLS -# → Choose SSL/TLS library for ESP-TLS … = (X) Custom TLS stack -idf.py build flash monitor -``` - -That's it — `esp-tls` calls now go through wolfSSL. - -## Alternative: path-based dependency (in-tree / forks) - -If you're working from a fork or vendor the component directly under -`components/esp-wolfssl/` in your project (e.g. while iterating on changes to -this repository), use a path-based dependency instead of the registry one. In -`main/idf_component.yml`: - -```yaml -dependencies: - esp-wolfssl: - path: ${PROJECT_DIR}/components/esp-wolfssl -``` - -The auto-registration mechanism is the same; only the way the component is -located on disk differs. - -## Verifying - -On boot, `esp-tls` logs a single line confirming that the wolfSSL stack -registered successfully: - -``` -I (xxx) esp-tls-custom-stack: Custom TLS stack registered successfully -``` - -If you do not see that line and `esp_tls_conn_*` calls return -`ESP_ERR_INVALID_STATE` / "No TLS stack registered", the `esp-wolfssl` -component was likely trimmed out of the build — double-check that -`main/idf_component.yml` lists `esp-wolfssl` (registry or path) as a -dependency. - -# Options (Debugging and more) -- `esp-wolfssl` options are available under `idf.py menuconfig -> Component Config -> wolfSSL`. - - - Enable ALPN ( Application Layer Protocol Negotiation ) in wolfSSL - - This option is enabled by default for wolfSSL, and can be disabled if not required. - - - Enable OCSP (Online Certificate Status Protocol) in wolfSSL - - This options is disabled by default. Enabling it adds support for checking the host's certificate revocation status - during the TLS handshake. - - - Enable Post-Quantum Cryptography (ML-KEM, ML-DSA, SHA-3/SHAKE) - - Disabled by default. Enabling it compiles in the native wolfSSL PQC implementations - (~30 kB of additional flash even when no PQC algorithm is used at runtime). - -- Compile-time tuning (cipher suites, TLS 1.3, debug logging via `DEBUG_WOLFSSL`, etc.) is done in - [port/user_settings.h](port/user_settings.h). Note that certificate chains are verified with - `WOLFSSL_ALT_CERT_CHAINS`, i.e. providing the root CA is sufficient even when the server sends - intermediates that are not in your trust store. - -- Certificate date (notBefore/notAfter) validation is **enabled**: the system clock must be set - (e.g. via SNTP, see the `https_request` example) before TLS connections are made, otherwise - the handshake fails with a certificate-date error. ---- -# Comparison of wolfSSL and mbedTLS - -The following table shows a typical comparison between wolfSSL and mbedtls when `https_request` (which has server authentication) was run with both -SSL/TLS libraries and with all respective configurations set to default. -_(mbedtls IN_CONTENT length and OUT_CONTENT length were set to 16384 bytes and 4096 bytes respectively)_ - -| Property | wolfSSL | mbedTLS | -|--------------------|----------|----------| -| Total Heap Consumed| ~19 Kb | ~37 Kb | -| Task Stack Used | ~2.2 Kb | ~3.6 Kb | -| Bin size | ~858 Kb | ~736 Kb | - -# Additional Pointers - -In general, these are links which will be useful for using both wolfSSL, as well as networked and secure applications in general. Furthermore, there is a more comprehensive tutorial that can be found in Chapter 11 of the official wolfSSL manual. The examples in the wolfSSL package and Chapter 11 do appropriate error checking, which is worth taking a look at. For a more comprehensive API, check out chapter 17 of the official manual. - -- wolfSSL Manual [https://www.wolfssl.com/docs/wolfssl-manual/]() -- wolfSSL GitHub - [https://github.com/wolfssl/wolfssl]() - +ESP-WOLFSSL +=========== + +# Licensing + + +--- +**IMPORTANT NOTE** + +Until March 2021, this repository contained binary distribution of wolfSSL libraries, which could be used royalty-free on all Espressif MCU products. This royalty-free binary distribution is not available anymore. + +This repository now uses upstream wolfSSL GitHub pointer as submodule and can still be used as ESP-IDF component. Please follow licensing requirements per [wolfssl/LICENSING](https://github.com/wolfSSL/wolfssl/blob/master/LICENSING) + +--- + +# Requirements +- ESP_IDF + - To use `esp-wolfssl` as the esp-tls custom TLS stack (recommended, see below), ESP-IDF v6.x or later (master) is required — `CONFIG_ESP_TLS_CUSTOM_STACK` is not available in earlier releases. + - To use the wolfSSL native APIs directly (as in `examples/wolfssl_client`), ESP-IDF v4.1 or later is sufficient. + - The IDF_PATH should be set as an environment variable + +# Getting Started + +- Please clone this repository using, + ``` + git clone --recursive https://github.com/espressif/esp-wolfssl + ``` +- Please refer to https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html for setting ESP-IDF + - ESP-IDF can be downloaded from https://github.com/espressif/esp-idf/ + - ESP-IDF v4.1 and above is recommended version +- Please refer to [example README](examples/README.md) for more information on setting up examples + +# Using esp-wolfssl as a custom esp-tls stack (ESP-IDF 6.x) + +From ESP-IDF 6.x onwards, `esp-tls` supports pluggable TLS backends via +`CONFIG_ESP_TLS_CUSTOM_STACK`. `esp-wolfssl` registers itself automatically +with `esp-tls` during system init (via `ESP_SYSTEM_INIT_FN`), so applications +that already use the `esp_tls_*` APIs (or any higher-level component built on +top — `esp_http_client`, `esp_https_ota`, `esp_https_server`, `esp-mqtt`, etc.) +work unchanged. **No code changes are needed in `app_main`; you do not need to +call `esp_wolfssl_register_stack()` explicitly.** + +The only requirement is that the `esp-wolfssl` component must be part of your +build so that the auto-registration init function gets linked in. This +component is not published to the IDF Component Registry, so clone it (see +[Getting Started](#getting-started)) and add it as a local, path-based +dependency in your project's `main/idf_component.yml`: + +```yaml +dependencies: + esp-wolfssl: + path: /path/to/esp-wolfssl +``` + +Equivalently, vendor the component under `components/esp-wolfssl/` in your +project, or point `EXTRA_COMPONENT_DIRS` at its location in your top-level +`CMakeLists.txt`. Either way the Component Manager / build system injects +`esp-wolfssl` into the build, so it is pulled in even under `MINIMAL_BUILD` +projects without any further wiring. + +Finally, enable the custom stack and (re)build: + +```bash +idf.py menuconfig +# → Component config +# → ESP-TLS +# → Choose SSL/TLS library for ESP-TLS … = (X) Custom TLS stack +idf.py build flash monitor +``` + +That's it — `esp-tls` calls now go through wolfSSL. + +## Verifying + +On boot, `esp-tls` logs a single line confirming that the wolfSSL stack +registered successfully: + +``` +I (xxx) esp-tls-custom-stack: Custom TLS stack registered successfully +``` + +If you do not see that line and `esp_tls_conn_*` calls return +`ESP_ERR_INVALID_STATE` / "No TLS stack registered", the `esp-wolfssl` +component was likely trimmed out of the build — double-check that +`main/idf_component.yml` lists `esp-wolfssl` (path-based) as a dependency. + +# Options (Debugging and more) +- `esp-wolfssl` options are available under `idf.py menuconfig -> Component Config -> wolfSSL`. + + - Enable ALPN ( Application Layer Protocol Negotiation ) in wolfSSL + - This option is enabled by default for wolfSSL, and can be disabled if not required. + + - Enable OCSP (Online Certificate Status Protocol) in wolfSSL + - This options is disabled by default. Enabling it adds support for checking the host's certificate revocation status + during the TLS handshake. + + - Enable Post-Quantum Cryptography (ML-KEM, ML-DSA, SHA-3/SHAKE) + - Disabled by default. Enabling it compiles in the native wolfSSL PQC implementations + (~30 kB of additional flash even when no PQC algorithm is used at runtime). + +- Compile-time tuning (cipher suites, TLS 1.3, debug logging via `DEBUG_WOLFSSL`, etc.) is done in + [port/user_settings.h](port/user_settings.h). Note that certificate chains are verified with + `WOLFSSL_ALT_CERT_CHAINS`, i.e. providing the root CA is sufficient even when the server sends + intermediates that are not in your trust store. + +- Certificate date (notBefore/notAfter) validation is **enabled**: the system clock must be set + (e.g. via SNTP, see the `https_request` example) before TLS connections are made, otherwise + the handshake fails with a certificate-date error. +--- +# Comparison of wolfSSL and mbedTLS + +The following table shows a typical comparison between wolfSSL and mbedtls when `https_request` (which has server authentication) was run with both +SSL/TLS libraries and with all respective configurations set to default. +_(mbedtls IN_CONTENT length and OUT_CONTENT length were set to 16384 bytes and 4096 bytes respectively)_ + +| Property | wolfSSL | mbedTLS | +|--------------------|----------|----------| +| Total Heap Consumed| ~19 Kb | ~37 Kb | +| Task Stack Used | ~2.2 Kb | ~3.6 Kb | +| Bin size | ~858 Kb | ~736 Kb | + +# Additional Pointers + +In general, these are links which will be useful for using both wolfSSL, as well as networked and secure applications in general. Furthermore, there is a more comprehensive tutorial that can be found in Chapter 11 of the official wolfSSL manual. The examples in the wolfSSL package and Chapter 11 do appropriate error checking, which is worth taking a look at. For a more comprehensive API, check out chapter 17 of the official manual. + +- wolfSSL Manual [https://www.wolfssl.com/docs/wolfssl-manual/]() +- wolfSSL GitHub + [https://github.com/wolfssl/wolfssl]()