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.
This commit is contained in:
Aditya Patwardhan
2026-02-03 19:27:09 +05:30
parent f965e08ac5
commit e1810e6bfd
4 changed files with 125 additions and 22 deletions
-2
View File
@@ -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})
@@ -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
}
+23 -4
View File
@@ -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 */
+57 -2
View File
@@ -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