From e1810e6bfd63aaba62399733f8cced83c071a1fc Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Tue, 3 Feb 2026 19:27:09 +0530 Subject: [PATCH] feat(esp-tls): Add crypto callbacks to custom TLS stack interface Added crypto_sha1 and crypto_base64_encode callbacks to esp_tls_stack_ops_t to allow custom TLS stacks to provide implementations for esp_crypto_* APIs. --- components/esp-tls/CMakeLists.txt | 2 - .../esp-tls/esp-tls-crypto/esp_tls_crypto.c | 59 ++++++++++++++----- components/esp-tls/esp_tls_custom_stack.c | 27 +++++++-- components/esp-tls/esp_tls_custom_stack.h | 59 ++++++++++++++++++- 4 files changed, 125 insertions(+), 22 deletions(-) diff --git a/components/esp-tls/CMakeLists.txt b/components/esp-tls/CMakeLists.txt index f153be305c..b5eabfe4dc 100644 --- a/components/esp-tls/CMakeLists.txt +++ b/components/esp-tls/CMakeLists.txt @@ -17,8 +17,6 @@ endif() idf_component_register(SRCS "${srcs}" INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} esp-tls-crypto PRIV_INCLUDE_DIRS "private_include" - # mbedtls is public requirements because esp_tls.h - # includes mbedtls header files. REQUIRES mbedtls PRIV_REQUIRES ${priv_req}) diff --git a/components/esp-tls/esp-tls-crypto/esp_tls_crypto.c b/components/esp-tls/esp-tls-crypto/esp_tls_crypto.c index f4ff1e4b47..6fdea8557e 100644 --- a/components/esp-tls/esp-tls-crypto/esp_tls_crypto.c +++ b/components/esp-tls/esp-tls-crypto/esp_tls_crypto.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,15 +8,21 @@ #include "esp_log.h" #include "esp_err.h" #include "sdkconfig.h" + +#if CONFIG_ESP_TLS_USING_MBEDTLS #include "mbedtls/base64.h" #include "mbedtls/error.h" #include "psa/crypto.h" +#endif -__attribute__((unused)) static const char *TAG = "esp_crypto"; +#if CONFIG_ESP_TLS_CUSTOM_STACK +#include "esp_tls_custom_stack.h" +#endif -static int esp_crypto_sha1_mbedtls( const unsigned char *input, - size_t ilen, - unsigned char output[20]) +#if CONFIG_ESP_TLS_USING_MBEDTLS +static int esp_crypto_sha1_mbedtls(const unsigned char *input, + size_t ilen, + unsigned char output[20]) { #if CONFIG_MBEDTLS_SHA1_C || CONFIG_MBEDTLS_HARDWARE_SHA psa_hash_operation_t ctx = PSA_HASH_OPERATION_INIT; @@ -39,27 +45,52 @@ exit: psa_hash_abort(&ctx); return status == PSA_SUCCESS ? 0 : -1; #else - ESP_LOGE(TAG, "Please enable CONFIG_MBEDTLS_SHA1_C or CONFIG_MBEDTLS_HARDWARE_SHA to support SHA1 operations"); + ESP_LOGE("esp_crypto", "Please enable CONFIG_MBEDTLS_SHA1_C or CONFIG_MBEDTLS_HARDWARE_SHA to support SHA1 operations"); return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED; #endif /* CONFIG_MBEDTLS_SHA1_C || CONFIG_MBEDTLS_HARDWARE_SHA*/ } -static int esp_crypto_bas64_encode_mbedtls( unsigned char *dst, size_t dlen, - size_t *olen, const unsigned char *src, - size_t slen) +static int esp_crypto_base64_encode_mbedtls(unsigned char *dst, size_t dlen, + size_t *olen, const unsigned char *src, + size_t slen) { return mbedtls_base64_encode(dst, dlen, olen, src, slen); } +#endif /* CONFIG_ESP_TLS_USING_MBEDTLS */ -int esp_crypto_sha1( const unsigned char *input, - size_t ilen, - unsigned char output[20]) +int esp_crypto_sha1(const unsigned char *input, + size_t ilen, + unsigned char output[20]) { +#if CONFIG_ESP_TLS_USING_MBEDTLS return esp_crypto_sha1_mbedtls(input, ilen, output); +#elif CONFIG_ESP_TLS_CUSTOM_STACK + int ret = esp_tls_custom_stack_crypto_sha1(input, ilen, output); + if (ret == ESP_ERR_NOT_SUPPORTED) { + ESP_LOGE("esp_crypto", "Custom TLS stack must implement crypto_sha1 callback"); + return -1; + } + return ret; +#else + ESP_LOGE("esp_crypto", "No TLS stack configured"); + return -1; +#endif } int esp_crypto_base64_encode(unsigned char *dst, size_t dlen, size_t *olen, - const unsigned char *src, size_t slen ) + const unsigned char *src, size_t slen) { - return esp_crypto_bas64_encode_mbedtls(dst, dlen, olen, src, slen); +#if CONFIG_ESP_TLS_USING_MBEDTLS + return esp_crypto_base64_encode_mbedtls(dst, dlen, olen, src, slen); +#elif CONFIG_ESP_TLS_CUSTOM_STACK + int ret = esp_tls_custom_stack_crypto_base64_encode(dst, dlen, olen, src, slen); + if (ret == ESP_ERR_NOT_SUPPORTED) { + ESP_LOGE("esp_crypto", "Custom TLS stack must implement crypto_base64_encode callback"); + return -1; + } + return ret; +#else + ESP_LOGE("esp_crypto", "No TLS stack configured"); + return -1; +#endif } diff --git a/components/esp-tls/esp_tls_custom_stack.c b/components/esp-tls/esp_tls_custom_stack.c index b25727ede5..ac4e92edfe 100644 --- a/components/esp-tls/esp_tls_custom_stack.c +++ b/components/esp-tls/esp_tls_custom_stack.c @@ -230,11 +230,30 @@ int esp_tls_custom_stack_server_session_continue_async(esp_tls_t *tls) void esp_tls_custom_stack_server_session_delete(esp_tls_t *tls) { - if (s_esp_tls_custom_stack == NULL || !s_esp_tls_custom_stack->server_session_delete) { - ESP_LOGE(TAG, "No TLS stack registered or server session not supported."); - return; + CHECK_STACK_REGISTERED_VOID(); + if (s_esp_tls_custom_stack->server_session_delete) { + s_esp_tls_custom_stack->server_session_delete(s_esp_tls_custom_stack_user_ctx, tls); + } else { + /* Fall back to conn_delete as documented */ + s_esp_tls_custom_stack->conn_delete(s_esp_tls_custom_stack_user_ctx, tls); } - s_esp_tls_custom_stack->server_session_delete(s_esp_tls_custom_stack_user_ctx, tls); +} + +int esp_tls_custom_stack_crypto_sha1(const unsigned char *input, size_t ilen, unsigned char output[20]) +{ + if (s_esp_tls_custom_stack == NULL || !s_esp_tls_custom_stack->crypto_sha1) { + return ESP_ERR_NOT_SUPPORTED; + } + return s_esp_tls_custom_stack->crypto_sha1(s_esp_tls_custom_stack_user_ctx, input, ilen, output); +} + +int esp_tls_custom_stack_crypto_base64_encode(unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen) +{ + if (s_esp_tls_custom_stack == NULL || !s_esp_tls_custom_stack->crypto_base64_encode) { + return ESP_ERR_NOT_SUPPORTED; + } + return s_esp_tls_custom_stack->crypto_base64_encode(s_esp_tls_custom_stack_user_ctx, dst, dlen, olen, src, slen); } #else /* CONFIG_ESP_TLS_CUSTOM_STACK */ diff --git a/components/esp-tls/esp_tls_custom_stack.h b/components/esp-tls/esp_tls_custom_stack.h index 6cf3b96cd4..83bcc9c23f 100644 --- a/components/esp-tls/esp_tls_custom_stack.h +++ b/components/esp-tls/esp_tls_custom_stack.h @@ -478,15 +478,63 @@ typedef struct esp_tls_stack_ops { * @note If NULL, conn_delete() will be used instead. */ void (*server_session_delete)(void *user_ctx, esp_tls_t *tls); + + /** + * @brief Calculate SHA1 hash (optional, for esp_crypto_sha1 API) + * + * This function calculates the SHA1 hash of the input data. It is used by + * esp_crypto_sha1() API which is needed by components like esp_http_server + * for WebSocket key calculation. + * + * @param user_ctx User context pointer passed to esp_tls_register_stack() + * @param input Input data buffer + * @param ilen Length of input data + * @param output Output buffer for SHA1 hash (must be at least 20 bytes) + * + * @return + * - 0: Success + * - Negative value: Error occurred + * + * @note If NULL, esp_crypto_sha1() API calls will fail. This callback must be implemented + * if your application or any dependent component (e.g., esp_http_server for WebSocket) + * uses the esp_crypto_sha1() API. + */ + int (*crypto_sha1)(void *user_ctx, const unsigned char *input, size_t ilen, unsigned char output[20]); + + /** + * @brief Base64 encode data (optional, for esp_crypto_base64_encode API) + * + * This function performs Base64 encoding of the source data. It is used by + * esp_crypto_base64_encode() API which is needed by components like esp_http_server + * for WebSocket key encoding. + * + * @param user_ctx User context pointer passed to esp_tls_register_stack() + * @param dst Destination buffer for encoded data + * @param dlen Size of destination buffer + * @param olen Pointer to store the number of bytes written + * @param src Source data buffer + * @param slen Length of source data + * + * @return + * - 0: Success + * - -0x002A: Buffer too small + * - Other negative value: Error occurred + * + * @note If NULL, esp_crypto_base64_encode() API calls will fail. This callback must be + * implemented if your application or any dependent component (e.g., esp_http_server + * for WebSocket) uses the esp_crypto_base64_encode() API. + */ + int (*crypto_base64_encode)(void *user_ctx, unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen); } esp_tls_stack_ops_t; /** * Compile-time check to detect structure layout changes. * If this assertion fails, you MUST increment ESP_TLS_STACK_OPS_VERSION. * - * Field count: 1 (version) + 21 (function pointers) = 22 + * Field count: 1 (version) + 23 (function pointers) = 24 */ -ESP_STATIC_ASSERT(sizeof(esp_tls_stack_ops_t) == 22 * sizeof(void *), "esp_tls_stack_ops_t layout changed - update ESP_TLS_STACK_OPS_VERSION!"); +ESP_STATIC_ASSERT(sizeof(esp_tls_stack_ops_t) == 24 * sizeof(void *), "esp_tls_stack_ops_t layout changed - update ESP_TLS_STACK_OPS_VERSION!"); /** * @brief Register a custom TLS stack implementation @@ -672,6 +720,13 @@ int esp_tls_custom_stack_server_session_continue_async(esp_tls_t *tls); /** @brief Delete server session */ void esp_tls_custom_stack_server_session_delete(esp_tls_t *tls); +/** @brief Calculate SHA1 hash using registered stack's implementation */ +int esp_tls_custom_stack_crypto_sha1(const unsigned char *input, size_t ilen, unsigned char output[20]); + +/** @brief Base64 encode using registered stack's implementation */ +int esp_tls_custom_stack_crypto_base64_encode(unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen); + /** @} */ #ifdef __cplusplus