mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
feat(esp_http): migrate esp_http to PSA API
This commit is contained in:
@@ -743,3 +743,4 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
- CONFIG_LIBC_PICOLIBC
|
||||
- CONFIG_GDMA_ENABLE_WEIGHTED_ARBITRATION
|
||||
- CONFIG_I3C_MASTER_ENABLED
|
||||
- CONFIG_MBEDTLS_ESP_IDF_USE_PSA_CRYPTO
|
||||
|
||||
@@ -4,10 +4,17 @@ else()
|
||||
set(req linux esp_event)
|
||||
endif()
|
||||
|
||||
if(CONFIG_ESP_HTTP_CLIENT_PSA_CRYPTO_MIGRATE)
|
||||
set(HTTP_CRYPTO_SRC "lib/http_crypto_psa.c")
|
||||
else()
|
||||
set(HTTP_CRYPTO_SRC "lib/http_crypto_mbedtls.c")
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "esp_http_client.c"
|
||||
"lib/http_auth.c"
|
||||
"lib/http_header.c"
|
||||
"lib/http_utils.c"
|
||||
${HTTP_CRYPTO_SRC}
|
||||
INCLUDE_DIRS "include"
|
||||
PRIV_INCLUDE_DIRS "lib/include"
|
||||
# lwip is a public requirement because esp_http_client.h includes sys/socket.h
|
||||
|
||||
@@ -41,4 +41,11 @@ menu "ESP HTTP client"
|
||||
help
|
||||
This config option helps in setting the time in millisecond to wait for event to be posted to the
|
||||
system default event loop. Set it to -1 if you need to set timeout to portMAX_DELAY.
|
||||
|
||||
config ESP_HTTP_CLIENT_PSA_CRYPTO_MIGRATE
|
||||
depends on MBEDTLS_ESP_IDF_USE_PSA_CRYPTO
|
||||
bool "Migrate ESP HTTP Client to use PSA Crypto"
|
||||
default y
|
||||
help
|
||||
Migrate ESP HTTP Client to use PSA Crypto.
|
||||
endmenu
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -12,17 +12,15 @@
|
||||
#include "sys/socket.h"
|
||||
#include "esp_rom_md5.h"
|
||||
#include "esp_tls_crypto.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
|
||||
#include "http_utils.h"
|
||||
#include "http_auth.h"
|
||||
#include "http_crypto.h"
|
||||
|
||||
#define MD5_MAX_LEN (33)
|
||||
#define SHA256_LEN (32)
|
||||
#define SHA256_HEX_LEN (65)
|
||||
#define HTTP_AUTH_BUF_LEN (1024)
|
||||
|
||||
static const char *TAG = "HTTP_AUTH";
|
||||
@@ -85,19 +83,13 @@ static int sha256_sprintf(char *sha, const char *fmt, ...)
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
mbedtls_sha256_context sha256;
|
||||
mbedtls_sha256_init(&sha256);
|
||||
if (mbedtls_sha256_starts(&sha256, 0) != 0) {
|
||||
goto exit;
|
||||
}
|
||||
if (mbedtls_sha256_update(&sha256, buf, len) != 0) {
|
||||
goto exit;
|
||||
}
|
||||
if (mbedtls_sha256_finish(&sha256, digest) != 0) {
|
||||
|
||||
esp_err_t err = http_crypto_sha256(buf, len, digest);
|
||||
if (err != ESP_OK) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (i = 0; i < 32; ++i) {
|
||||
for (i = 0; i < SHA256_LEN; ++i) {
|
||||
sprintf(&sha[i * 2], "%02x", (unsigned int)digest[i]);
|
||||
}
|
||||
sha[SHA256_HEX_LEN - 1] = '\0';
|
||||
@@ -105,7 +97,6 @@ static int sha256_sprintf(char *sha, const char *fmt, ...)
|
||||
|
||||
exit:
|
||||
free(buf);
|
||||
mbedtls_sha256_free(&sha256);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "http_crypto.h"
|
||||
#include "esp_rom_md5.h"
|
||||
#include "esp_err.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "http_crypto_mbedtls";
|
||||
|
||||
|
||||
esp_err_t http_crypto_sha256(const uint8_t *data, size_t data_len, uint8_t *hash)
|
||||
{
|
||||
if (data == NULL || data_len == 0 || hash == NULL) {
|
||||
ESP_LOGE(TAG, "Invalid input parameters");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t err = ESP_FAIL;
|
||||
mbedtls_sha256_context ctx;
|
||||
mbedtls_sha256_init(&ctx);
|
||||
|
||||
if (mbedtls_sha256_starts(&ctx, false) != 0) {
|
||||
ESP_LOGE(TAG, "Failed to start SHA-256 hash");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (mbedtls_sha256_update(&ctx, data, data_len) != 0) {
|
||||
ESP_LOGE(TAG, "Failed to update SHA-256 hash");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (mbedtls_sha256_finish(&ctx, hash) != 0) {
|
||||
ESP_LOGE(TAG, "Failed to finish SHA-256 hash");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
err = ESP_OK;
|
||||
|
||||
exit:
|
||||
mbedtls_sha256_free(&ctx);
|
||||
return err;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "esp_err.h"
|
||||
#include "http_crypto.h"
|
||||
#include "psa/crypto.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "http_crypto_psa";
|
||||
|
||||
esp_err_t http_crypto_sha256(const uint8_t *data, size_t data_len, uint8_t *hash)
|
||||
{
|
||||
if (data == NULL || data_len == 0 || hash == NULL) {
|
||||
ESP_LOGE(TAG, "Invalid input parameters");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
size_t hash_len = 0;
|
||||
psa_status_t status = psa_hash_compute(PSA_ALG_SHA_256, data, data_len, hash, SHA256_LEN, &hash_len);
|
||||
if (status != PSA_SUCCESS || hash_len != SHA256_LEN) {
|
||||
ESP_LOGE(TAG, "Failed to compute SHA-256 hash");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
|
||||
#define SHA256_LEN (32)
|
||||
#define SHA256_HEX_LEN (65)
|
||||
|
||||
esp_err_t http_crypto_sha256(const uint8_t *data, size_t data_len, uint8_t *hash);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -2,12 +2,19 @@ set(priv_req mbedtls lwip esp_timer)
|
||||
set(priv_inc_dir "src/util" "src/port/esp32")
|
||||
set(requires http_parser esp_event)
|
||||
|
||||
if(CONFIG_HTTPD_SERVER_PSA_CRYPTO_MIGRATE)
|
||||
set(HTTPD_CRYPTO_SRC "src/httpd_crypto_psa.c")
|
||||
else()
|
||||
set(HTTPD_CRYPTO_SRC "src/httpd_crypto_mbedtls.c")
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "src/httpd_main.c"
|
||||
"src/httpd_parse.c"
|
||||
"src/httpd_sess.c"
|
||||
"src/httpd_txrx.c"
|
||||
"src/httpd_uri.c"
|
||||
"src/httpd_ws.c"
|
||||
${HTTPD_CRYPTO_SRC}
|
||||
"src/util/ctrl_sock.c"
|
||||
INCLUDE_DIRS "include"
|
||||
PRIV_INCLUDE_DIRS ${priv_inc_dir}
|
||||
|
||||
@@ -72,4 +72,11 @@ menu "HTTP Server"
|
||||
Enable this option to use WebSocket pre-handshake callback. This will allow the server to register
|
||||
a callback function that will be called before the WebSocket handshake is processed i.e. before switching
|
||||
to the WebSocket protocol.
|
||||
|
||||
config HTTPD_SERVER_PSA_CRYPTO_MIGRATE
|
||||
depends on MBEDTLS_ESP_IDF_USE_PSA_CRYPTO
|
||||
bool "Migrate ESP HTTP Server to use PSA Crypto"
|
||||
default y
|
||||
help
|
||||
Migrate ESP HTTP Server to use PSA Crypto.
|
||||
endmenu
|
||||
|
||||
@@ -593,6 +593,8 @@ esp_err_t httpd_sess_trigger_close_(httpd_handle_t handle, struct sock_db *sessi
|
||||
*/
|
||||
void esp_http_server_dispatch_event(int32_t event_id, const void* event_data, size_t event_data_size);
|
||||
|
||||
esp_err_t httpd_crypto_sha1(const uint8_t *data, size_t data_len, uint8_t *hash);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "mbedtls/sha1.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "httpd_crypto_mbedtls";
|
||||
|
||||
#define SHA1_LEN (20)
|
||||
|
||||
esp_err_t httpd_crypto_sha1(const uint8_t *data, size_t data_len, uint8_t *hash)
|
||||
{
|
||||
if (data == NULL || data_len == 0 || hash == NULL) {
|
||||
ESP_LOGE(TAG, "Invalid input parameters");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t err = ESP_FAIL;
|
||||
mbedtls_sha1_context ctx;
|
||||
mbedtls_sha1_init(&ctx);
|
||||
|
||||
if (mbedtls_sha1_starts(&ctx) != 0) {
|
||||
ESP_LOGE(TAG, "Failed to start SHA-1 hash");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (mbedtls_sha1_update(&ctx, data, data_len) != 0) {
|
||||
ESP_LOGE(TAG, "Failed to update SHA-1 hash");
|
||||
goto exit;
|
||||
}
|
||||
if (mbedtls_sha1_finish(&ctx, hash) != 0) {
|
||||
ESP_LOGE(TAG, "Failed to finish SHA-1 hash");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
err = ESP_OK;
|
||||
|
||||
exit:
|
||||
mbedtls_sha1_free(&ctx);
|
||||
return err;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "psa/crypto.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "httpd_crypto_psa";
|
||||
|
||||
#define SHA1_LEN (20)
|
||||
|
||||
esp_err_t httpd_crypto_sha1(const uint8_t *data, size_t data_len, uint8_t *hash)
|
||||
{
|
||||
if (data == NULL || data_len == 0 || hash == NULL) {
|
||||
ESP_LOGE(TAG, "Invalid input parameters");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
size_t hash_len = 0;
|
||||
psa_status_t status = psa_hash_compute(PSA_ALG_SHA_1, data, data_len, hash, SHA1_LEN, &hash_len);
|
||||
if (status != PSA_SUCCESS || hash_len != SHA1_LEN) {
|
||||
ESP_LOGE(TAG, "Failed to compute SHA-1 hash");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <sys/random.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_err.h>
|
||||
#include <mbedtls/sha1.h>
|
||||
|
||||
#include <mbedtls/base64.h>
|
||||
#include <mbedtls/error.h>
|
||||
|
||||
@@ -143,35 +143,15 @@ esp_err_t httpd_ws_respond_server_handshake(httpd_req_t *req, const char *suppor
|
||||
|
||||
ESP_LOGD(TAG, LOG_FMT("Server key before encoding: %s"), server_raw_text);
|
||||
|
||||
/* Generate SHA-1 first and then encode to Base64 */
|
||||
size_t key_len = strlen(server_raw_text);
|
||||
|
||||
#if CONFIG_MBEDTLS_SHA1_C || CONFIG_MBEDTLS_HARDWARE_SHA
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
mbedtls_sha1_context ctx;
|
||||
mbedtls_sha1_init(&ctx);
|
||||
|
||||
if ((ret = mbedtls_sha1_starts(&ctx)) != 0) {
|
||||
goto sha_end;
|
||||
}
|
||||
|
||||
if ((ret = mbedtls_sha1_update(&ctx, (uint8_t *)server_raw_text, key_len)) != 0) {
|
||||
goto sha_end;
|
||||
}
|
||||
|
||||
if ((ret = mbedtls_sha1_finish(&ctx, server_key_hash)) != 0) {
|
||||
goto sha_end;
|
||||
}
|
||||
|
||||
sha_end:
|
||||
mbedtls_sha1_free(&ctx);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "Error in calculating SHA1 sum , returned 0x%02X", ret);
|
||||
return ESP_FAIL;
|
||||
esp_err_t err = httpd_crypto_sha1((const uint8_t *)server_raw_text, strlen(server_raw_text), server_key_hash);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to compute SHA-1 hash");
|
||||
return err;
|
||||
}
|
||||
#else
|
||||
ESP_LOGE(TAG, "Please enable CONFIG_MBEDTLS_SHA1_C or CONFIG_MBEDTLS_HARDWARE_SHA to support SHA1 operations");
|
||||
return ESP_FAIL;
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
#endif /* CONFIG_MBEDTLS_SHA1_C || CONFIG_MBEDTLS_HARDWARE_SHA */
|
||||
|
||||
size_t encoded_len = 0;
|
||||
|
||||
@@ -79,6 +79,9 @@ SECONDARY: 102: init_rng in components/esp_hw_support/hw_random.c on BIT(0)
|
||||
# Security specific initializations
|
||||
SECONDARY: 103: esp_security_init in components/esp_security/src/init.c on BIT(0)
|
||||
|
||||
# PSA Crypto initialization (must happen after esp_security_init for hardware crypto support)
|
||||
SECONDARY: 104: mbedtls_psa_crypto_init_fn in components/mbedtls/port/esp_psa_crypto_init.c on BIT(0)
|
||||
|
||||
# esp_sleep doesn't have init dependencies
|
||||
SECONDARY: 105: esp_sleep_startup_init in components/esp_hw_support/sleep_gpio.c on BIT(0)
|
||||
SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/port/esp32c5/sleep_clock.c on BIT(0)
|
||||
|
||||
@@ -167,6 +167,10 @@ list(APPEND mbedtls_targets everest p256m)
|
||||
set(mbedtls_target_sources "${COMPONENT_DIR}/port/mbedtls_debug.c"
|
||||
"${COMPONENT_DIR}/port/esp_platform_time.c")
|
||||
|
||||
if(CONFIG_MBEDTLS_ESP_IDF_USE_PSA_CRYPTO)
|
||||
list(APPEND mbedtls_target_sources "${COMPONENT_DIR}/port/esp_psa_crypto_init.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_MBEDTLS_DYNAMIC_BUFFER)
|
||||
set(mbedtls_target_sources ${mbedtls_target_sources}
|
||||
"${COMPONENT_DIR}/port/dynamic/esp_mbedtls_dynamic_impl.c"
|
||||
@@ -357,14 +361,14 @@ foreach(target ${mbedtls_targets})
|
||||
endif()
|
||||
if(CONFIG_MBEDTLS_COMPILER_OPTIMIZATION_SIZE)
|
||||
target_compile_options(${target} PRIVATE "-Os")
|
||||
elseif(CONFIG_MBEDTLS_COMPILER_OPTIMIZATION_SPEED)
|
||||
elseif(CONFIG_MBEDTLS_COMPILER_OPTIMIZATION_PERF)
|
||||
target_compile_options(${target} PRIVATE "-O2")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(CONFIG_MBEDTLS_COMPILER_OPTIMIZATION_SIZE)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Os")
|
||||
elseif(CONFIG_MBEDTLS_COMPILER_OPTIMIZATION_SPEED)
|
||||
elseif(CONFIG_MBEDTLS_COMPILER_OPTIMIZATION_PERF)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-O2")
|
||||
endif()
|
||||
|
||||
@@ -398,6 +402,9 @@ endif()
|
||||
|
||||
target_link_libraries(${COMPONENT_LIB} ${linkage_type} ${mbedtls_targets})
|
||||
|
||||
# Ensure PSA crypto initialization is included in the build
|
||||
target_link_libraries(${COMPONENT_LIB} ${linkage_type} "-u mbedtls_psa_crypto_init_include_impl")
|
||||
|
||||
if(CONFIG_ESP_TLS_USE_DS_PERIPHERAL)
|
||||
# The linker seems to be unable to resolve all the dependencies without increasing this
|
||||
set_property(TARGET mbedcrypto APPEND PROPERTY LINK_INTERFACE_MULTIPLICITY 6)
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
menu "mbedTLS"
|
||||
|
||||
menu "Core Configuration"
|
||||
|
||||
config MBEDTLS_ESP_IDF_USE_PSA_CRYPTO
|
||||
depends on IDF_EXPERIMENTAL_FEATURES
|
||||
bool "Enable the Platform Security Architecture (PSA) cryptography API for ESP-IDF"
|
||||
default y
|
||||
help
|
||||
Enable the Platform Security Architecture (PSA) cryptography API for ESP-IDF.
|
||||
This option migrates from mbedtls API to PSA Crypto API. This increases code size.
|
||||
|
||||
choice MBEDTLS_COMPILER_OPTIMIZATION
|
||||
prompt "Compiler optimization level"
|
||||
default MBEDTLS_COMPILER_OPTIMIZATION_NONE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -10,6 +10,9 @@
|
||||
#include <stdio.h>
|
||||
#include "esp_random.h"
|
||||
#include "mbedtls/esp_mbedtls_random.h"
|
||||
#if defined(MBEDTLS_PLATFORM_GET_ENTROPY_ALT)
|
||||
#include "psa/crypto.h"
|
||||
#endif
|
||||
|
||||
#include <entropy_poll.h>
|
||||
|
||||
@@ -31,3 +34,33 @@ int mbedtls_esp_random(void *ctx, unsigned char *buf, size_t len)
|
||||
esp_fill_random(buf, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_PLATFORM_GET_ENTROPY_ALT)
|
||||
int mbedtls_platform_get_entropy(unsigned char *output, size_t output_size,
|
||||
size_t *output_len, size_t *entropy_content);
|
||||
|
||||
psa_status_t mbedtls_psa_external_get_random(
|
||||
mbedtls_psa_external_random_context_t *context,
|
||||
uint8_t *output, size_t output_size, size_t *output_length)
|
||||
{
|
||||
if (context == NULL || output == NULL || output_length == NULL) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
esp_fill_random(output, output_size);
|
||||
*output_length = output_size;
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
int mbedtls_platform_get_entropy(unsigned char *output, size_t output_size,
|
||||
size_t *output_len, size_t *entropy_content)
|
||||
{
|
||||
if (output == NULL || output_size == 0 || output_len == NULL || entropy_content == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
esp_fill_random(output, output_size);
|
||||
*output_len = output_size;
|
||||
*entropy_content = 8 * output_size;
|
||||
return 0;
|
||||
}
|
||||
#endif // MBEDTLS_PLATFORM_GET_ENTROPY_ALT
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_private/startup_internal.h"
|
||||
#include "psa/crypto.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
void mbedtls_psa_crypto_init_include_impl(void);
|
||||
|
||||
/**
|
||||
* @brief Initialize PSA Crypto library at system startup
|
||||
*
|
||||
* This function is called during the SECONDARY initialization stage with priority 104,
|
||||
* which ensures it runs after esp_security_init (priority 103). This ordering guarantees
|
||||
* that hardware crypto support is fully initialized before PSA crypto initialization.
|
||||
*/
|
||||
ESP_SYSTEM_INIT_FN(mbedtls_psa_crypto_init_fn, SECONDARY, BIT(0), 104)
|
||||
{
|
||||
psa_status_t status = psa_crypto_init();
|
||||
if (status != PSA_SUCCESS) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void mbedtls_psa_crypto_init_include_impl(void)
|
||||
{
|
||||
// Linker hook, exists for no other purpose
|
||||
}
|
||||
@@ -36,6 +36,12 @@
|
||||
* \{
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_IDF_TARGET_LINUX
|
||||
#define MBEDTLS_PLATFORM_GET_ENTROPY_ALT
|
||||
#define MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
|
||||
#endif // !CONFIG_IDF_TARGET_LINUX
|
||||
#define MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS
|
||||
|
||||
/**
|
||||
* \def MBEDTLS_HAVE_TIME
|
||||
*
|
||||
|
||||
@@ -9,16 +9,31 @@ from pytest_embedded_idf.utils import idf_parametrize
|
||||
|
||||
|
||||
@pytest.mark.httpbin
|
||||
@pytest.mark.parametrize(
|
||||
'config',
|
||||
[
|
||||
'default', # mbedTLS crypto backend
|
||||
'psa', # PSA crypto backend (tests system integration, HTTPS stack usage)
|
||||
],
|
||||
indirect=True,
|
||||
)
|
||||
@idf_parametrize('target', ['esp32'], indirect=['target'])
|
||||
def test_examples_protocol_esp_http_client(dut: Dut) -> None:
|
||||
"""
|
||||
steps: |
|
||||
1. join AP/Ethernet
|
||||
2. Send HTTP request to httpbin.org
|
||||
|
||||
Tests both mbedTLS and PSA crypto backends.
|
||||
The PSA config specifically tests:
|
||||
- PSA crypto initialization
|
||||
- HTTPS with PSA (stack/heap usage)
|
||||
- SHA256 Digest Auth with PSA
|
||||
- Full integration under real workload
|
||||
"""
|
||||
binary_file = os.path.join(dut.app.binary_path, 'esp_http_client_example.bin')
|
||||
bin_size = os.path.getsize(binary_file)
|
||||
logging.info('esp_http_client_bin_size : {}KB'.format(bin_size // 1024))
|
||||
logging.info(f'esp_http_client_bin_size : {bin_size // 1024}KB')
|
||||
# start test
|
||||
dut.expect('Connected to AP, begin http example', timeout=30)
|
||||
dut.expect(r'HTTP GET Status = 200, content_length = (\d)')
|
||||
@@ -46,7 +61,7 @@ def test_examples_protocol_esp_http_client(dut: Dut) -> None:
|
||||
dut.expect(r'HTTP chunk encoding Status = 200, content_length = (-?\d)')
|
||||
# content-len for chunked encoding is typically -1, could be a positive length in some cases
|
||||
dut.expect(r'HTTP Stream reader Status = 200, content_length = (\d)')
|
||||
dut.expect(r'HTTPS Status = 200, content_length = (\d)')
|
||||
dut.expect(r'HTTPS Status = 200, content_length = (-?\d)')
|
||||
dut.expect(r'HTTPS Status = 200, content_length = (\d)')
|
||||
dut.expect(r'Last esp error code: 0x8001')
|
||||
dut.expect(r'HTTP GET Status = 200, content_length = (\d)')
|
||||
@@ -71,8 +86,7 @@ def test_examples_protocol_esp_http_client_dynamic_buffer(dut: Dut) -> None:
|
||||
# check and log bin size
|
||||
binary_file = os.path.join(dut.app.binary_path, 'esp_http_client_example.bin')
|
||||
bin_size = os.path.getsize(binary_file)
|
||||
logging.info('esp_http_client_bin_size : {}KB'.format(bin_size // 1024))
|
||||
|
||||
logging.info(f'esp_http_client_bin_size : {bin_size // 1024}KB')
|
||||
dut.expect('Connected to AP, begin http example', timeout=30)
|
||||
dut.expect(r'HTTP GET Status = 200, content_length = (\d)')
|
||||
dut.expect(r'HTTP POST Status = 200, content_length = (\d)')
|
||||
|
||||
@@ -11,3 +11,4 @@ CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH=y
|
||||
CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH=y
|
||||
CONFIG_EXAMPLE_HTTP_ENDPOINT="httpbin.espressif.cn"
|
||||
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_CROSS_SIGNED_VERIFY=y
|
||||
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# HTTP Client Example with PSA Crypto API
|
||||
# This config tests the PSA crypto backend instead of direct mbedTLS
|
||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||
CONFIG_EXAMPLE_ETH_PHY_GENERIC=y
|
||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
|
||||
CONFIG_EXAMPLE_CONNECT_IPV6=y
|
||||
CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH=y
|
||||
CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH=y
|
||||
CONFIG_EXAMPLE_HTTP_ENDPOINT="httpbin.espressif.cn"
|
||||
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||
# PSA Crypto Configuration
|
||||
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
|
||||
CONFIG_MBEDTLS_ESP_IDF_USE_PSA_CRYPTO=y
|
||||
CONFIG_ESP_HTTP_CLIENT_PSA_CRYPTO_MIGRATE=y
|
||||
@@ -12,3 +12,4 @@ CONFIG_MBEDTLS_DYNAMIC_BUFFER=y
|
||||
CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y
|
||||
CONFIG_MBEDTLS_DHM_C=y
|
||||
CONFIG_EXAMPLE_HTTP_ENDPOINT="httpbin.espressif.cn"
|
||||
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
|
||||
list(APPEND sdkconfig_defaults ${CMAKE_CURRENT_LIST_DIR}/ws_echo_server_mbedtls_config.conf)
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
|
||||
idf_build_set_property(MINIMAL_BUILD ON)
|
||||
|
||||
@@ -30,7 +30,7 @@ class WsClient:
|
||||
self.uri = uri
|
||||
|
||||
def __enter__(self): # type: ignore
|
||||
self.ws.connect('ws://{}:{}/{}'.format(self.ip, self.port, self.uri))
|
||||
self.ws.connect(f'ws://{self.ip}:{self.port}/{self.uri}')
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback): # type: ignore
|
||||
@@ -48,12 +48,24 @@ class WsClient:
|
||||
|
||||
|
||||
@pytest.mark.wifi_router
|
||||
@pytest.mark.parametrize(
|
||||
'config',
|
||||
[
|
||||
'default', # mbedTLS crypto backend
|
||||
'psa', # PSA crypto backend (tests SHA-1 for WebSocket handshake)
|
||||
],
|
||||
indirect=True,
|
||||
)
|
||||
@idf_parametrize('target', ['esp32'], indirect=['target'])
|
||||
def test_examples_protocol_http_ws_echo_server(dut: Dut) -> None:
|
||||
"""
|
||||
Test WebSocket echo server with both mbedTLS and PSA crypto backends.
|
||||
This specifically tests the SHA-1 computation used in WebSocket handshake (RFC 6455).
|
||||
"""
|
||||
# Get binary file
|
||||
binary_file = os.path.join(dut.app.binary_path, 'ws_echo_server.bin')
|
||||
bin_size = os.path.getsize(binary_file)
|
||||
logging.info('http_ws_server_bin_size : {}KB'.format(bin_size // 1024))
|
||||
logging.info(f'http_ws_server_bin_size : {bin_size // 1024}KB')
|
||||
|
||||
logging.info('Starting ws-echo-server test app based on http_server')
|
||||
|
||||
@@ -68,8 +80,8 @@ def test_examples_protocol_http_ws_echo_server(dut: Dut) -> None:
|
||||
got_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
|
||||
got_port = dut.expect(r"Starting server on port: '(\d+)'", timeout=30)[1].decode()
|
||||
|
||||
logging.info('Got IP : {}'.format(got_ip))
|
||||
logging.info('Got Port : {}'.format(got_port))
|
||||
logging.info(f'Got IP : {got_ip}')
|
||||
logging.info(f'Got Port : {got_port}')
|
||||
|
||||
# Start ws server test
|
||||
with WsClient(got_ip, int(got_port), uri='ws') as ws:
|
||||
@@ -77,32 +89,41 @@ def test_examples_protocol_http_ws_echo_server(dut: Dut) -> None:
|
||||
for expected_opcode in [OPCODE_TEXT, OPCODE_BIN, OPCODE_PING]:
|
||||
ws.write(data=DATA, opcode=expected_opcode)
|
||||
opcode, data = ws.read()
|
||||
logging.info('Testing opcode {}: Received opcode:{}, data:{}'.format(expected_opcode, opcode, data))
|
||||
logging.info(f'Testing opcode {expected_opcode}: Received opcode:{opcode}, data:{data}')
|
||||
data = data.decode()
|
||||
if expected_opcode == OPCODE_PING:
|
||||
dut.expect('Got a WS PING frame, Replying PONG')
|
||||
if opcode != OPCODE_PONG or data != DATA:
|
||||
raise RuntimeError('Failed to receive correct opcode:{} or data:{}'.format(opcode, data))
|
||||
raise RuntimeError(f'Failed to receive correct opcode:{opcode} or data:{data}')
|
||||
continue
|
||||
dut_data = dut.expect(r'Got packet with message: ([A-Za-z0-9_]*)')[1]
|
||||
dut_opcode = dut.expect(r'Packet type: ([0-9]*)')[1].decode()
|
||||
|
||||
if opcode != expected_opcode or data != DATA or opcode != int(dut_opcode) or (data not in str(dut_data)):
|
||||
raise RuntimeError('Failed to receive correct opcode:{} or data:{}'.format(opcode, data))
|
||||
raise RuntimeError(f'Failed to receive correct opcode:{opcode} or data:{data}')
|
||||
ws.write(data='Trigger async', opcode=OPCODE_TEXT)
|
||||
opcode, data = ws.read()
|
||||
logging.info('Testing async send: Received opcode:{}, data:{}'.format(opcode, data))
|
||||
logging.info(f'Testing async send: Received opcode:{opcode}, data:{data}')
|
||||
data = data.decode()
|
||||
if opcode != OPCODE_TEXT or data != 'Async data':
|
||||
raise RuntimeError('Failed to receive correct opcode:{} or data:{}'.format(opcode, data))
|
||||
raise RuntimeError(f'Failed to receive correct opcode:{opcode} or data:{data}')
|
||||
|
||||
|
||||
@pytest.mark.wifi_router
|
||||
@pytest.mark.parametrize(
|
||||
'config',
|
||||
[
|
||||
'default', # mbedTLS crypto backend
|
||||
'psa', # PSA crypto backend (tests SHA-1 for WebSocket handshake)
|
||||
],
|
||||
indirect=True,
|
||||
)
|
||||
@idf_parametrize('target', ['esp32'], indirect=['target'])
|
||||
def test_ws_auth_handshake(dut: Dut) -> None:
|
||||
"""
|
||||
Test that connecting to /ws does NOT print the handshake success log.
|
||||
This is used to verify ws_pre_handshake_cb can reject the handshake.
|
||||
Tests both mbedTLS and PSA crypto backends.
|
||||
"""
|
||||
# Wait for device to connect and start server
|
||||
if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# WebSocket Echo Server Example with PSA Crypto API
|
||||
# This config tests the PSA crypto backend for WebSocket handshake (SHA-1)
|
||||
CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y
|
||||
CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y
|
||||
# PSA Crypto Configuration
|
||||
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
|
||||
CONFIG_MBEDTLS_ESP_IDF_USE_PSA_CRYPTO=y
|
||||
CONFIG_HTTPD_SERVER_PSA_CRYPTO_MIGRATE=y
|
||||
@@ -0,0 +1,8 @@
|
||||
CONFIG_MBEDTLS_TLS_ENABLED=n
|
||||
CONFIG_MBEDTLS_MD5_C=n
|
||||
CONFIG_MBEDTLS_SHA224_C=n
|
||||
CONFIG_MBEDTLS_SHA256_C=n
|
||||
CONFIG_MBEDTLS_SHA384_C=n
|
||||
CONFIG_MBEDTLS_SHA512_C=n
|
||||
CONFIG_MBEDTLS_SHA3_C=n
|
||||
CONFIG_MBEDTLS_ROM_MD5=n
|
||||
Reference in New Issue
Block a user